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>

したがって、一部のビジュアル設定とラベル テキストは分離コード ファイルのプロパティにバインドされます。

これらの Drawing 図形を使用して 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 dynamic-loaded xaml

洞察に感謝します

編集 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見えることがわかります。コマンドを 1 回実行するshape.geometryCanvas.LayoutTransformと、恒等行列になります。2 回目の実行時shape.geometryCanvas.LayoutTransformは、TransformGroup2 つの要素の です。

(Xamlで宣言された)の参照geometryCanvasは、画面で使用されているものではないようです。

4

1 に答える 1

1

とった!

逆シリアル化後、コード ビハインド ファイルの外部から x:Name で指定された 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 に答える