2012-09-24 41 views
0

我的问题如下:在我的程序中,我让用户在Canvas上放置形状(类DrawingShape)。绘图外形封装堆叠路径和标签:在XamlReader解析后恢复绑定

<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()shape.EndUpdate()Bindings not applied to dynamically-loaded xaml

非常感谢任何见解

编辑2012年9月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.LayoutTransform是两个元素的一个TransformGroup

它在某种程度上看起来像geometryCanvas(在Xaml中声明)的参考不是屏幕上使用的参考。

回答

1

Got it!

我不知道在解序列化之后,您不能成功引用x:来自代码隐藏文件外部的名称为XAML的元素(至少这似乎是问题的关键)。

一种解决方法是在用户控件使用FindName(),如:

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); 

的作品就像更简单和优雅的soluti通过dbaseman与建议:

shape.DataContext = this; 

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