2009-06-16 4 views
3

У меня есть UserControl WPF с ListBox и ContentPanel. ListBox привязан к ObservableCollection, в котором есть яблоки и апельсины.привязка данных к гетерогенному списку

Что считается правильным способом его настройки, поэтому, если я выбираю яблоко, я вижу AppleEditor справа, и если я выберу оранжевый, на панели содержимого появится OrangeEditor?

ответ

5

Я бы предложил использовать DataTemplating для создания и применения различных редакторов. В зависимости от того, насколько отличаются ваши «яблоки» и «апельсины», я бы рекомендовал использовать DataTemplateSelector. Кроме того, если у них есть что-то вроде свойства Type, вы также можете использовать DataTriggers для выключения редакторов.

Позволяет создать небольшой образец с яблоками и апельсинами. У них будут общие свойства, а также несколько разных свойств. И тогда мы можем создать ObservableCollection базовых IFruits для использования в пользовательском интерфейсе.

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, что будет просто проверить тип фруктов и назначить правильное 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

Спасибо за супер подробный ответ. –

+0

Кроме того, могу ли я использовать селектор шаблонов для выбора между двумя различными UserControls вместо отдельных шаблонов? –

+0

Если вы хотите переключиться между UserControls, а затем взгляните на использование DataTrigger и установите Content в Setter Trigger. – rmoore

Смежные вопросы