在通过XamlReader解析的UserControl上设置Canvas.Left

时间:2012-09-20 12:27:58

标签: wpf canvas user-controls drag-and-drop xamlreader

我和WPF玩了一下。我想要做的是将自定义控件从模板调色板窗口拖到另一个窗口的画布,并在那里创建该自定义控件的克隆。这与您在Visio中看到的非常相似。

为了从调色板克隆模板控件,我滥用了XamlWriter和XamlReader的序列化和反序列化功能。

在我的drop-callback中,我有以下代码:

private void drawingCanvas_Drop(object sender, DragEventArgs e)
{
    DrawingShape shape = (DrawingShape)e.Data.GetData(typeof(DrawingShape));
    if (shape != null)
    {
        Canvas target = this.drawingCanvas;
        Point p = e.GetPosition(target);

        string xamlString = System.Windows.Markup.XamlWriter.Save(shape);
        DrawingShape c = (DrawingShape)System.Windows.Markup.XamlReader.Parse(xamlString);

        Canvas.SetLeft(c, p.X - c.Width / 2);
        Canvas.SetTop(c, p.Y - c.Height / 2);
        target.Children.Add(c);

        this.shapesPalette.shapesGallery.ClearValue(ListView.SelectedIndexProperty);
    }
}

我的用户控件如下所示:

<UserControl x:Class="MyNamespace.Graphics.DrawingShape"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="60" d:DesignWidth="60">
    <Grid Width="Auto" Height="Auto" >
        <Grid.RowDefinitions>
            <RowDefinition Height="38"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Canvas HorizontalAlignment="Center" Grid.Row="0" Width="38" Height="38" Canvas.Left="0" Canvas.Top="0">
            <Path x:Name="Path" Width="35.8774" Height="31.2047" Canvas.Left="1.0613" Canvas.Top="3.29528" Stretch="Fill" StrokeLineJoin="Round" Stroke="#FF230FD2" Fill="#FF0096FF" Data="F1 M 19,3.79528L 1.5613,34L 36.4387,34L 19,3.79528 Z "/>
        </Canvas>
        <Label x:Name="Label" HorizontalAlignment="Center" Grid.Row="1">MyLabel</Label>
    </Grid>
</UserControl>

但是,Canvas.SetLeft()Canvas.SetTop()不做任何事情。克隆始终添加到目标画布的左上角。如果我使用任何其他WPF-Control而不是我的用户控件,则此代码可以正常工作。

我想,克隆的用户控件还没有成为任何视觉层次结构的一部分。但是,我想知道为了使上面的代码工作,MS控件做得更好。由于我是WPF的新手,我不确定我应该寻找什么来修复我的用户控件。任何指针都非常感谢。

1 个答案:

答案 0 :(得分:0)

我已经通过XamlWriter / XamlReader(仅用于原型设计)离开克隆,现在在执行布局后使用ActualWidth / ActualHeight更新:

private void drawingCanvas_Drop(object sender, DragEventArgs e)
{
    DrawingShape templateShape = (DrawingShape)e.Data.GetData(typeof(DrawingShape));
    if (templateShape != null)
    {
        Canvas target = this.drawingCanvas;
        Point p = e.GetPosition(target);

        DrawingShape addedShape = new DrawingShape();
        addedShape.IsDraggingEnabled = true;

        target.Children.Add(addedShape);
        addedShape.UpdateLayout();
        addedShape.RenderTransform = new TranslateTransform(p.X - addedShape.ActualWidth / 2, p.Y - addedShape.ActualHeight / 2);
        this.shapesPalette.shapesGallery.ClearValue(ListView.SelectedIndexProperty);
    }
}

但是,我希望此解决方案能够与XamlWriter / XamlReader克隆一起使用。