2009-06-16 35 views
3

我有一个WPF用户控件与ListBox和ContentPanel。 ListBox绑定到一个ObservableCollection,其中包含苹果和桔子。数据绑定到一个异构列表

什么被认为是正确的方式来设置它,所以如果我选择一个苹果,我看到右侧的AppleEditor,如果我选择一个橙色的OrangeEditor显示在内容面板?

回答

5

我建议使用DataTemplating来创建和应用不同的编辑器。根据你的'苹果'和'橘子'的不同,我会推荐使用DataTemplateSelector。另外,如果他们有类似属性的东西,你也可以使用DataTriggers来切换编辑器。

让我们用苹果和橘子做一个小样本。他们将拥有一些共享的属性,以及一些不同的属性。然后我们可以创建一个用于UI的基础IFruits的ObservableCollection。

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 
} 

接下来,我们可以创建DataTemplateSelector,它将检查Fruit的类型并分配正确的DataTemplate。

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

然后在用户界面中,我们可以创建一个苹果和橘子两个模板,并使用选择,以确定哪些被应用到我们的内容。

<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

感谢您的超级详细的答案。 – 2009-06-16 20:28:37