11

XAML で定義されたパスがあります。

<UserControl.Resources>
    <ResourceDictionary>
        <Path x:Key="N44" Width="20" Height="80" Stretch="Fill" Fill="#FF000000" Data="M 20,25.2941L 20,29.4118L 15.9091,29.4118L 15.9091,40L 12.2727,40L 12.2727,29.4118L 2.54313e-006,29.4118L 2.54313e-006,25.6985L 13.4872,7.62939e-006L 15.9091,7.62939e-006L 15.9091,25.2941L 20,25.2941 Z M 12.2727,25.2941L 12.2727,5.28493L 2.09517,25.2941L 12.2727,25.2941 Z M 20,65.2941L 20,69.4118L 15.9091,69.4118L 15.9091,80L 12.2727,80L 12.2727,69.4118L -5.08626e-006,69.4118L -5.08626e-006,65.6985L 13.4872,40L 15.9091,40L 15.9091,65.2941L 20,65.2941 Z M 12.2727,65.2941L 12.2727,45.2849L 2.09517,65.2941L 12.2727,65.2941 Z "/>
    </ResourceDictionary>
</UserControl.Resources>

私はそれをWPF Girdに追加したいと思っています。

System.Windows.Shapes.Path aPath = new System.Windows.Shapes.Path();
aPath = (System.Windows.Shapes.Path)this.Resources["N44"];
LayoutRoot.Children.Add(aPath); 

ただし、ボタン クリック イベントにこのコードを追加してからボタンを 2 回クリックすると、次のエラーがスローされます。

「指定されたビジュアルは、すでに別のビジュアルの子であるか、CompositionTarget のルートです。」

その後、リソースの 2 つのインスタンスを作成しようとしましたが、引き続き同じエラーが発生します。以下は、このテストに使用したコードです。

private void cmbTest_Click(object sender, System.Windows.RoutedEventArgs e)
  {
   System.Windows.Shapes.Path aPath = new System.Windows.Shapes.Path();
   aPath = (System.Windows.Shapes.Path)this.Resources["N44"];

   if (LayoutRoot.Children.Contains(aPath) == true){
    System.Windows.Shapes.Path bPath = (System.Windows.Shapes.Path)this.Resources["N44"];
    LayoutRoot.Children.Add(bPath); 
   }else{
    aPath.Name = "a";
    aPath.Tag = "a";
    LayoutRoot.Children.Add(aPath);
   }
  }

そのため、実行時に ResourceDictionary で定義された XAML パスを WPF フォームに複数回追加するにはどうすればよいですか?

4

3 に答える 3

15

これを行うには、組み込みの簡単な方法があります。リソースに x:Shared="False" を設定します。これにより、再利用が可能になります。その後、何度でもご利用いただけます。

<UserControl.Resources>
    <ResourceDictionary>
        <Path x:Shared="False" x:Key="N44" Width="20" Height="80" Stretch="Fill" Fill="#FF000000" Data="..."/>
    </ResourceDictionary>
</UserControl.Resources>
于 2010-05-12T17:15:45.517 に答える
12

その後、MSDN のドキュメントの重要な部分を見逃していたことに気付きました。

共有可能な型と UIElement の型:

リソース ディクショナリは、XAML で共有可能な型とこれらの型の値を定義するための手法です。すべての型または値が ResourceDictionary からの使用に適しているわけではありません。Silverlight で共有可能と見なされる型の詳細については、「リソース ディクショナリ」を参照してください。

特に、すべての UIElement 派生型は、テンプレートおよび特定のコントロール インスタンスでのテンプレートの適用に由来しない限り、共有できません。テンプレートの場合を除き、UIElement は一度インスタンス化されるとオブジェクト ツリー内の 1 か所にのみ存在すると予想され、UIElement を共有可能にすると、この原則に違反する可能性があります。

要約すると、そのコードを実行するたびに新しいインスタンスを作成するのではなく、オブジェクトへの参照を作成するだけなので、それは機能する方法ではありません。したがって、もう少し読んだ後、問題を解決するための3つの潜在的な方法を思いつきました。

1)手法を使用して、新しいオブジェクトへのディープ コピーを作成します。他の StackOverflow の質問の例 -ディープ クローニング オブジェクト

2) XAML をアプリケーション内の文字列に格納し、XAML リーダーを使用してパスのインスタンスを作成します。

System.Windows.Shapes.Path newPath = (System.Windows.Shapes.Path)System.Windows.Markup.XamlReader.Parse("<Path xmlns='http://schemas.microsoft.com/winfx/2006/xaml/presentation'  Width='20' Height='80' Stretch='Fill' Fill='#FF000000' Data='M 20,25.2941L 20,29.4118L 15.9091,29.4118L 15.9091,40L 12.2727,40L 12.2727,29.4118L 2.54313e-006,29.4118L 2.54313e-006,25.6985L 13.4872,7.62939e-006L 15.9091,7.62939e-006L 15.9091,25.2941L 20,25.2941 Z M 12.2727,25.2941L 12.2727,5.28493L 2.09517,25.2941L 12.2727,25.2941 Z M 20,65.2941L 20,69.4118L 15.9091,69.4118L 15.9091,80L 12.2727,80L 12.2727,69.4118L -5.08626e-006,69.4118L -5.08626e-006,65.6985L 13.4872,40L 15.9091,40L 15.9091,65.2941L 20,65.2941 Z M 12.2727,65.2941L 12.2727,45.2849L 2.09517,65.2941L 12.2727,65.2941 Z ' HorizontalAlignment='Left' VerticalAlignment='Top' Margin='140,60,0,0'/>");
LayoutRoot.Children.Add(newPath);

3)パス データのみをリソース ディクショナリに格納します。コードで Path の新しいインスタンスを作成し、Path データを新しい Path に適用してから、関心のある他のプロパティを手動で追加します。

XAML - パス データは StreamGeometry として格納されます。

<UserControl.Resources>
    <ResourceDictionary>
        <StreamGeometry x:Key="N44">M 20,25.2941L 20,29.4118L 15.9091,29.4118L 15.9091,40L 12.2727,40L 12.2727,29.4118L 2.54313e-006,29.4118L 2.54313e-006,25.6985L 13.4872,7.62939e-006L 15.9091,7.62939e-006L 15.9091,25.2941L 20,25.2941 Z M 12.2727,25.2941L 12.2727,5.28493L 2.09517,25.2941L 12.2727,25.2941 Z M 20,65.2941L 20,69.4118L 15.9091,69.4118L 15.9091,80L 12.2727,80L 12.2727,69.4118L -5.08626e-006,69.4118L -5.08626e-006,65.6985L 13.4872,40L 15.9091,40L 15.9091,65.2941L 20,65.2941 Z M 12.2727,65.2941L 12.2727,45.2849L 2.09517,65.2941L 12.2727,65.2941 Z</StreamGeometry>
    </ResourceDictionary>
</UserControl.Resources>

次にインスタンスを作成し、他の値を適用する C# コード:

System.Windows.Shapes.Path bPath = new System.Windows.Shapes.Path();
bPath.Data = (System.Windows.Media.Geometry)this.FindResource("N44");

bPath.Width = 20;
bPath.Height = 80;

bPath.VerticalAlignment = System.Windows.VerticalAlignment.Top;
bPath.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;

left = left + 40;

System.Windows.Thickness thickness = new System.Windows.Thickness(left,100,0,0);
bPath.Margin = thickness;

bPath.Fill = System.Windows.Media.Brushes.Black;
LayoutRoot.Children.Add(bPath);
于 2009-09-05T00:15:16.603 に答える
3

パスのスタイルを作成して適用するだけです。

于 2009-09-04T07:55:16.270 に答える