1

我的问题如下:在我的程序中,我让用户在画布上放置形状(类 DrawingShape)。Drawing Shape 封装了一个堆叠的路径和标签:

<UserControl x:Class="HandballTrainerFluent.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"
             DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <Grid x:Name="container" Width="Auto" Height="Auto">
        <Grid.RowDefinitions>
            <RowDefinition Height="38"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Canvas x:Name="geometryCanvas" HorizontalAlignment="Center" Grid.Row="0" Width="38" Height="38">
            <Path x:Name="Path"
                  Width="35.8774"
                  Height="31.2047"
                  Canvas.Left="1.0613"
                  Canvas.Top="3.29528"
                  Stretch="Fill"
                  StrokeLineJoin="Round"
                  Stroke="{Binding OutlineBrush,Mode=OneWay}"
                  StrokeThickness="{Binding OutlineWidth,Mode=OneWay}"
                  StrokeDashArray="{Binding OutlinePattern,Mode=OneWay}"
                  Fill="{Binding FillBrush,Mode=OneWay}"
                  Data="F1 M 19,3.79528L 1.5613,34L 36.4387,34L 19,3.79528 Z "/>
        </Canvas>
        <TextBlock x:Name="TextBox" HorizontalAlignment="Center" Grid.Row="1" Text="{Binding LabelText,Mode=OneWay}"></TextBlock>
    </Grid>
</UserControl>

所以一些视觉设置和标签文本绑定到代码隐藏文件的属性。

使用这些绘图形状反序列化 Canvas 后,我需要恢复 XAML 和代码隐藏文件之间的绑定。我试过这个,但它似乎不起作用:

private void RepairBindingsAfterLoading()
{
    foreach (UIElement element in this.drawingCanvas.Children)
    {
        if (element.GetType() == typeof(DrawingShape))
        {
            DrawingShape shape = (DrawingShape)element;
            BindingOperations.ClearAllBindings(shape.Path);
            BindingOperations.ClearAllBindings(shape.TextBox);
            BindingOperations.ClearAllBindings(shape);

            shape.BeginInit();
            Binding dataContextBinding = new Binding();
            dataContextBinding.RelativeSource = RelativeSource.Self;
            shape.SetBinding(DrawingShape.DataContextProperty, dataContextBinding);

            Binding fillBinding = new Binding("FillBrush");
            shape.Path.SetBinding(Path.FillProperty, fillBinding);
            Binding outlineBinding = new Binding("OutlineBrush");
            shape.Path.SetBinding(Path.StrokeProperty, outlineBinding);
            Binding widthBinding = new Binding("OutlineWidth");
            shape.Path.SetBinding(Path.StrokeThicknessProperty, widthBinding);
            Binding patternBinding = new Binding("OutlinePattern");
            shape.Path.SetBinding(Path.StrokeDashArrayProperty, patternBinding);

            Binding labelTextBinding = new Binding("LabelText");
            shape.TextBox.SetBinding(TextBlock.TextProperty, labelTextBinding);
            shape.EndInit();
            shape.UpdateLayout();
        }
    }
}

无论我对代码隐藏属性做什么(例如更改 FillBrush),所显示的 DrawingShape 的视觉效果都不会更新。我在这里错过了重要的一步吗?

我在看到这个问题后添加了:shape.BeginUpdate()Bindings not applied to dynamic-loaded xamlshape.EndUpdate()

非常感谢您的任何见解

编辑 2012-09-25

查看另一段不依赖于任何绑定的代码让我想知道,我是否可以在反序列化后通过它们的 x:Name 实际引用 Xaml-Definition 中的任何元素。以下回调不对形状执行任何操作:

private void rotateClockwiseMenuItem_Click(object sender, RoutedEventArgs e)
{
    if(this.drawingCanvas.SelectedItem.GetType() == typeof(DrawingShape))
    {
        DrawingShape shape = (DrawingShape)this.drawingCanvas.SelectedItem;
        TransformGroup transformStack = new TransformGroup();
        transformStack.Children.Add(shape.geometryCanvas.LayoutTransform);
        transformStack.Children.Add(new RotateTransform(90));
        shape.geometryCanvas.LayoutTransform = transformStack;
    }
}

调试告诉我,内容shape似乎刚刚好。当我执行一次命令时,shape.geometryCanvas.LayoutTransform是单位矩阵。第二次执行时,shape.geometryCanvas.LayoutTransformTransformGroup两个元素中的一个。

不知何故,看起来geometryCanvas(在 Xaml 中声明的)的参考不是屏幕上使用的参考。

4

1 回答 1

1

知道了!

我不知道您无法在反序列化后从代码隐藏文件外部成功引用 x:Name'd XAML 元素(至少这似乎是手头的问题)。

一个解决方案是FindName()在 UserControl 上使用,例如:

TextBlock textBox = shape.FindName("TextBox") as TextBlock;

完整正确的RepairBindingsAfterLoading()样子是这样的:

private void RepairBindingsAfterLoading()
{
    foreach (UIElement element in this.drawingCanvas.Children)
    {
        if (element.GetType() == typeof(DrawingShape))
        {
            DrawingShape shape = (DrawingShape)element;
            shape.DataContext = shape;

            Path path = shape.FindName("Path") as Path;
            Binding fillBinding = new Binding("FillBrush");
            path.SetBinding(Path.FillProperty, fillBinding);
            Binding outlineBinding = new Binding("OutlineBrush");
            path.SetBinding(Path.StrokeProperty, outlineBinding);
            Binding widthBinding = new Binding("OutlineWidth");
            path.SetBinding(Path.StrokeThicknessProperty, widthBinding);
            Binding patternBinding = new Binding("OutlinePattern");
            path.SetBinding(Path.StrokeDashArrayProperty, patternBinding);

            TextBlock textBox = shape.FindName("TextBox") as TextBlock;
            Binding labelTextBinding = new Binding("LabelText");
            textBox.SetBinding(TextBlock.TextProperty, labelTextBinding);
        }
    }
}

只是为了记录,我的笨拙

BindingOperations.ClearAllBindings(shape.Path);
BindingOperations.ClearAllBindings(shape.TextBox);
BindingOperations.ClearAllBindings(shape);

就像 dbaseman 建议的更简单和优雅的解决方案一样工作:

shape.DataContext = this;

希望这可以帮助其他人避免我的错误:-)

于 2012-09-25T08:20:50.113 回答