Frage

Ich möchte instantiate Objekte in XAML, und diese Instanzen wiederverwenden. Ich denke, es sollte einfach sein, aber ich bin stecken, bin ich wahrscheinlich etwas fehlt offensichtlich.

sagen, ich will Katzen hinzufügen, um verschiedene Zimmer (Zimmer verfügt über eine ObservableCollection Objekte vom Typ Cat enthält). In den UserControl.Resources ich schaffen 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>

In meinem Usercontrol möchte ich die Katzen zu den Zimmern hinzuzufügen:

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

Was ist die Syntax für das Hinzufügen der Cat-Instanzen auf die ObservableCollection Room.Cats? Zum Beispiel möchte ich Cat1 und Cat2 zu Room1 und Cat2 und Cat3 zu Room2 hinzuzufügen. Bin ich völlig auf dem Holzweg?

War es hilfreich?

Lösung 2

Basierend auf dem Feedback von Heinzi und Robert Rossney Ich kam mit der folgenden Lösung, die Arbeiten mit einer ObservableCollection, dass ich in XAML und Code hinter zugreifen kann:

Code erweiterte ich ObservableCollection, damit ich es in XAML verwenden kann (dies wird nicht mehr nötig sein, in XAML 2009):

public class CatObservableCollection : ObservableCollection<Cat> { }

In XAML in den UserControl.Resources instanziiert ich die Katzen:

<local:Cat x:Key="Tom" Name="Tom"/>
<local:Cat x:Key="Garfield" Name="Garfield"/>
<local:Cat x:Key="Furball" Name="Furball"/>

Die Sammlungen:

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

Die Zimmer sind nun wie folgt definiert:

<local:Room x:Name="Room1" Cats="{StaticResource Room1Collection}"/>
<local:Room x:Name="Room2" Cats="{StaticResource Room2Collection}"/>

Room.Cats ist ein ObservableCollection

Andere Tipps

Wiederverwenden von einzelnen Instanzen die Art und Weise Sie versuchen zu tun, es schwierig ist. Dies liegt daran, die Art und Weise, dass Sie in der Regel einzelne Objekte in XAML Referenz mit der StaticResource Markup-Erweiterung ist, und Sie können nur die Markup-Erweiterung verwenden, um eine Eigenschaft Wert zu setzen.

So können Sie leicht eine Eigenschaft vom Typ Cat auf eine Instanz eines Cat festlegen:

<Room Cat="{StaticResource Cat1}"/>

Sie können jedoch nicht eine Sammlung füllen, indem eine Eigenschaft festlegen.

Die Antwort überraschenderweise ist Ihre Objekte direkt in XAML instanziiert, anstatt sie in ObjectDataProviders der Verpackung. Sie verwenden immer noch die ObjectDataProvider, aber anders:

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

Für Ihre ganz speziellen Bedürfnisse, Sie für Generika gehen. Und deklarativ Generika zu verwenden, müssen Sie verwenden x: Typearguments Richtlinie . Typearguments-Richtlinie kann nur mit Root-Elemente verwendet werden. So müssen Sie sich jetzt für lose XAML-Datei gehen. Eine lose XAML-Datei kann mit System.Windows.Markup.XamlReader.Load(Stream Stream) method gelesen werden

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-Klasse:

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

So, Ihre TXT-Datei XAML-Code enthalten wäre:

<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>
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top