インスタンス化およびXAML内のオブジェクトの再利用事例
-
27-09-2019 - |
質問
私は、XAMLでインスタンス化オブジェクトにしたい、そしてこれらのインスタンスを再利用します。私はおそらく何かを明らかに欠けている、私はそれが簡単であるべきだと思うが、私はこだわってます。
と言う私は別の部屋(ルームタイプの猫のオブジェクトを含むのObservableCollectionを持っている)に猫を追加したいです。 UserControl.Resourcesで私はObjectDataProvidersを作成します:
<ObjectDataProvider x:Key="Cat1" ObjectType="{x:Type local:Cat}">
<ObjectDataProvider.ConstructorParameters>
<System:String>Tom</System:String>
</ObjectDataProvider.ConstructorParameters>
</ObjectDataProvider>
<ObjectDataProvider x:Key="Cat2" ObjectType="{x:Type local:Cat}">
<ObjectDataProvider.ConstructorParameters>
<System:String>Garfield</System:String>
</ObjectDataProvider.ConstructorParameters>
</ObjectDataProvider>
<ObjectDataProvider x:Key="Cat3" ObjectType="{x:Type local:Cat}">
<ObjectDataProvider.ConstructorParameters>
<System:String>Furball</System:String>
</ObjectDataProvider.ConstructorParameters>
</ObjectDataProvider>
私のユーザーコントロールでは、私は部屋に猫を追加する:
<local:Room x:Name="Room1">
<local:Room.Cats>
</local:Room.Cats>
<local:Room>
<local:Room x:Name="Room2">
<local:Room.Cats>
</local:Room.Cats>
<local:Room>
のObservableCollectionのRoom.CatsにCatインスタンスを追加するための構文は何ですか?たとえば、私はROOM2にCAT1とCat2のROOM1に、そしてCat2のとCAT3を追加したいです。完全に間違ってトラック上アムI?
解決 2
は、私が後ろにXAMLとコードにアクセスできることのObservableCollectionで動作し、次の解決策を考え出しました 私はXAML(これはもはやXAML 2009年に必要となります)でそれを使用できるように、
のコードでは、私はのObservableCollectionを拡張します:
public class CatObservableCollection : ObservableCollection<Cat> { }
私は猫をインスタンス化UserControl.ResourcesででXAMLます:
<local:Cat x:Key="Tom" Name="Tom"/>
<local:Cat x:Key="Garfield" Name="Garfield"/>
<local:Cat x:Key="Furball" Name="Furball"/>
コレクション:
<local:CatObservableCollection x:Key="Room1Collection">
<StaticResourceExtension ResourceKey="Tom"/>
<StaticResourceExtension ResourceKey="Garfield"/>
</local:CatObservableCollection>
<local:CatObservableCollection x:Key="Room2Collection">
<StaticResourceExtension ResourceKey="Garfield"/>
<StaticResourceExtension ResourceKey="Furball"/>
</local:CatObservableCollection>
次のようにお部屋は現在定義されています:
<local:Room x:Name="Room1" Cats="{StaticResource Room1Collection}"/>
<local:Room x:Name="Room2" Cats="{StaticResource Room2Collection}"/>
Room.CatsでのObservableCollectionである<猫>
他のヒント
は、個々のインスタンスを再利用すると、あなたはそれをやろうとしている方法は、注意が必要です。あなたは、一般的にXAMLで、単一のオブジェクトを参照する方法がStaticResource
のマークアップ拡張機能であるため、これは、あなたが唯一のプロパティ値を設定することマークアップ拡張機能を使用することができます。
あなたが簡単にCat
のインスタンスに型Cat
のプロパティを設定することができますので、
<Room Cat="{StaticResource Cat1}"/>
しかし、あなたがプロパティを設定して、コレクションを移入することはできません。
答えは、驚くべきことに、ObjectDataProvider
sでそれらをラップするのではなく、XAMLで直接あなたのオブジェクトをインスタンス化することです。あなたはまだObjectDataProvider
を使用していますが、異なっます:
<Window x:Class="ObjectDataProviderDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:ObjectDataProviderDemo"
xmlns:Collections="clr-namespace:System.Collections;assembly=mscorlib"
Title="MainWindow"
Height="350"
Width="525">
<Window.Resources>
<local:Cat x:Key="Tom" Name="Tom"/>
<local:Cat x:Key="Garfield" Name="Garfield"/>
<local:Cat x:Key="Furball" Name="Furball"/>
<Collections:ArrayList x:Key="CatList1">
<ObjectDataProvider ObjectInstance="{StaticResource Tom}" />
<ObjectDataProvider ObjectInstance="{StaticResource Garfield}" />
<ObjectDataProvider ObjectInstance="{StaticResource Furball}" />
</Collections:ArrayList>
<Collections:ArrayList x:Key="CatList2">
<ObjectDataProvider ObjectInstance="{StaticResource Tom}" />
<ObjectDataProvider ObjectInstance="{StaticResource Furball}" />
</Collections:ArrayList>
<DataTemplate x:Key="CatTemplate">
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</Window.Resources>
<StackPanel>
<ListBox ItemsSource="{StaticResource CatList1}"
ItemTemplate="{StaticResource CatTemplate}"/>
<ListBox ItemsSource="{StaticResource CatList2}"
ItemTemplate="{StaticResource CatTemplate}" />
</StackPanel>
</Window>
あなたの非常に具体的なニーズのために、あなたは、ジェネリック医薬品のために行くことができません。そして、宣言ジェネリックを使用するには、 Xを使用する必要があります。 TypeArguments指令する。 TypeArgumentsディレクティブは唯一のルート要素で使用することができます。だから、あなたは今緩いXAMLファイルのために行く必要があります。緩いXAMLファイルはSystem.Windows.Markup.XamlReader.Load(Stream Stream) method
を使用して読み取ることができます。
Cat.csます:
using System;
namespace WpfCollection._3840371
{
public class Cat
{
public Cat() { }
public Cat(String name, String color) { Name = name; Color = color; }
public String Name { get; set; }
public String Color { get; set; }
}
}
Room.csます:
using System;
using System.Collections.ObjectModel;
namespace WpfCollection._3840371
{
public class Room<T> where T : System.Windows.Data.ObjectDataProvider
{
public Room()
{
Cats = new ObservableCollection<T>();
}
public ObservableCollection<T> Cats { get; set; }
}
}
Windowクラスます:
namespace WpfCollection._3840371
{
/// <summary>
/// Interaction logic for Win3840371.xaml
/// </summary>
public partial class Win3840371 : Window
{
public Win3840371()
{
InitializeComponent();
Room<ObjectDataProvider> kitchenRoom;
using (FileStream fs = new FileStream(@"3840371/roomcats.txt", FileMode.Open))
{
kitchenRoom = (Room<ObjectDataProvider>)XamlReader.Load(fs);
}
foreach (ObjectDataProvider o in kitchenRoom.Cats)
Debug.WriteLine(((Cat)o.Data).Name + " : " + ((Cat)o.Data).Color);
}
}
}
だから、XAMLコードを含むあなたの.txtファイルは以下のようになります:
<local:Room
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:System="clr-namespace:System;assembly=mscorlib"
xmlns:local="clr-namespace:WpfCollection._3840371;assembly=WpfCollection"
x:Key="UpperRoom" x:TypeArguments="ObjectDataProvider">
<local:Room.Cats>
<ObjectDataProvider x:Key="Cat1" ObjectType="{x:Type local:Cat}">
<ObjectDataProvider.ConstructorParameters>
<System:String>Tom</System:String>
<System:String>Red</System:String>
</ObjectDataProvider.ConstructorParameters>
</ObjectDataProvider>
<ObjectDataProvider x:Key="Cat2" ObjectType="{x:Type local:Cat}">
<ObjectDataProvider.ConstructorParameters>
<System:String>Rubia</System:String>
<System:String>Brown</System:String>
</ObjectDataProvider.ConstructorParameters>
</ObjectDataProvider>
</local:Room.Cats>
</local:Room>