2009-06-16 17 views
3

Ich habe ein WPF UserControl mit einer ListBox und ContentPanel. Die ListBox ist an eine ObservableCollection gebunden, in der Äpfel und Orangen enthalten sind.Datenbindung an eine heterogene Liste

Was ist der richtige Weg, um es einrichten zu lassen, wenn ich einen Apfel auswähle, sehe ich einen AppleEditor auf der rechten Seite und wenn ich eine Orange wähle, erscheint ein OrangeEditor im Inhaltsfeld?

Antwort

5

Ich würde vorschlagen, DataTemplating zu verwenden, um die verschiedenen Editoren zu erstellen und anzuwenden. Abhängig davon, wie unterschiedlich Ihre "Äpfel" und "Orangen" sind, würde ich empfehlen, eine DataTemplateSelector zu verwenden. Wenn sie eine Type-Eigenschaft haben, könnten Sie auch DataTriggers verwenden, um die Editoren zu wechseln.

Lass uns eine kleine Probe mit Äpfeln und Orangen aufstellen. Sie werden einige gemeinsame Eigenschaften und einige andere Eigenschaften haben. Und dann können wir eine ObservableCollection der Basis-IFruits erstellen, die in der Benutzeroberfläche verwendet werden.

public partial class Window1 : Window 
{ 
    public ObservableCollection<IFruit> Fruits { get; set; } 
    public Window1() 
    { 
     InitializeComponent(); 

     Fruits = new ObservableCollection<IFruit>(); 
     Fruits.Add(new Apple { AppleType = "Granny Smith", HasWorms = false }); 
     Fruits.Add(new Orange { OrangeType = "Florida Orange", VitaminCContent = 75 }); 
     Fruits.Add(new Apple { AppleType = "Red Delicious", HasWorms = true }); 
     Fruits.Add(new Orange { OrangeType = "Navel Orange", VitaminCContent = 130 }); 

     this.DataContext = this; 
    } 
} 

public interface IFruit 
{ 
    string Name { get; } 
    string Color { get; } 
} 

public class Apple : IFruit 
{ 
    public Apple() { } 
    public string AppleType { get; set; } 
    public bool HasWorms { get; set; } 
    #region IFruit Members 
    public string Name { get { return "Apple"; } } 
    public string Color { get { return "Red"; } } 
    #endregion 
} 

public class Orange : IFruit 
{ 
    public Orange() { } 
    public string OrangeType { get; set; } 
    public int VitaminCContent { get; set; } 
    #region IFruit Members 
    public string Name { get { return "Orange"; } } 
    public string Color { get { return "Orange"; } } 
    #endregion 
} 

Als nächstes können wir schaffen Datatemplateselector, die nur die Art der Frucht überprüfen und die richtige Datatemplate zuweisen.

public class FruitTemplateSelector : DataTemplateSelector 
{ 
    public override DataTemplate SelectTemplate(object item, DependencyObject container) 
    { 
     string templateKey = null; 

     if (item is Orange) 
     { 
      templateKey = "OrangeTemplate"; 
     } 
     else if (item is Apple) 
     { 
      templateKey = "AppleTemplate"; 
     } 

     if (templateKey != null) 
     { 
      return (DataTemplate)((FrameworkElement)container).FindResource(templateKey); 
     } 
     else 
     { 
      return base.SelectTemplate(item, container); 
     } 
    } 
} 

Dann in der Benutzeroberfläche, können wir die beiden Vorlagen für Äpfel und Orangen, und verwenden Sie den Wähler, um zu bestimmen zu schaffen, die auf unsere Inhalte angewendet wird.

<Window x:Class="FruitSample.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:FruitSample" 
    Title="Fruits" 
    Height="300" 
    Width="300"> 
<Window.Resources> 

    <local:FruitTemplateSelector x:Key="Local_FruitTemplateSelector" /> 

    <DataTemplate x:Key="AppleTemplate"> 
     <StackPanel Background="{Binding Color}"> 
      <TextBlock Text="{Binding AppleType}" /> 
      <TextBlock Text="{Binding HasWorms, StringFormat=Has Worms: {0}}" /> 
     </StackPanel> 
    </DataTemplate> 

    <DataTemplate x:Key="OrangeTemplate"> 
     <StackPanel Background="{Binding Color}"> 
      <TextBlock Text="{Binding OrangeType}" /> 
      <TextBlock Text="{Binding VitaminCContent, StringFormat=Has {0} % of daily Vitamin C}" /> 
     </StackPanel> 
    </DataTemplate> 

</Window.Resources> 

<DockPanel> 
    <ListBox x:Name="uiFruitList" 
      ItemsSource="{Binding Fruits}" 
      DisplayMemberPath="Name" /> 
    <ContentControl Content="{Binding Path=SelectedItem, ElementName=uiFruitList}" 
        ContentTemplateSelector="{StaticResource Local_FruitTemplateSelector}"/> 
</DockPanel> 
</Window> 
+0

Danke für die super detaillierte Antwort. –

+0

Kann ich auch eine Vorlagenauswahl verwenden, um zwischen zwei verschiedenen Benutzersteuerelementen anstelle von separaten Vorlagen zu wählen? –

+0

Wenn Sie zwischen UserControls wechseln möchten, sollten Sie stattdessen einen DataTrigger verwenden und den Inhalt im Trigger-Setter festlegen. – rmoore

Verwandte Themen