WPF基于绑定值创建不同的ListBox行模板

时间:2015-01-28 14:43:28

标签: c# wpf xaml listbox

我目前没有任何代码可供分享。只是一个设计问题。

我有一个定义标签的类,以及一个关联的条目类型,我想将它绑定到ListBox。如果类型是例如"邮政编码",我需要ListBox将行创建为TextBlock和TextBox。对于"是/否",我需要知道在它旁边创建一个带有CheckBox的TextBlock。这些不同的行类型可能有7个或8个。

最好的方法是什么?

3 个答案:

答案 0 :(得分:2)

查看ItemTemplateSelector属性。此属性允许您提供自定义逻辑,用于选择要用于集合中每个项目的模板。

首先在资源字典中定义各种模板......

<Application>
  <Application.Resources>
    <DataTemplate x:Key="TextBoxTemplate">
      <!-- template here -->
    </DataTemplate>
    <DataTemplate x:Key="CheckBoxTemplate">
      <!-- template here -->
    </DataTemplate>
  </Application.Resources>
</Application>

然后,创建一个自定义DataTemplateSelector ...

public class MyTemplateSelector : DataTemplateSelector
{
  public override DataTemplate SelectTemplate(object item, DependencyObject container)
  {
    var myObj= item as MyObject;
    if (myObj != null) 
    {
      if (myObj.MyType is PostalCode)
      {
         return Application.Resources["TextBoxTemplate"] as DataTemplate;
      }
      if (myObj.MyType  is YesNo)
      {
        return Application.Resources["CheckBoxTemplate"] as DataTemplate;
      }
    }

    return null; 
  }
}

然后,只需使用ItemTemplateSelector属性......

<Window>
  <Window.Resources>
    <local:MyTemplateSelector x:Key="tempSelector" />
  </Window.Resources>
  <ListBox ItemSource="{Binding items}" ItemTemplateSelector="{StaticResource tempSelector}" />
</Window>

答案 1 :(得分:1)

您可以使用DataTrigger 类。

  

DataTrigger允许您在数据对象的属性值与指定值匹配时设置属性值。

或者,您可以使用DataTemplateSelector 类。

  

通常,如果对同一类型的对象具有多个DataTemplate,并且希望提供自己的逻辑以根据每个数据对象的属性选择要应用的DataTemplate,则可以创建DataTemplateSelector。

答案 2 :(得分:1)

解决此问题的最佳方法是让一个集合属性包含您希望在ListBox中看到的所有项目,将该集合绑定到显示项目列表的控件,并使用不同的数据模板,用于更改用于每种类型项目的视觉效果。

例如,您可能有邮政编码类型:

public class PostalCodeEntry
{
    public string Value { get; set; }  // Implement using standard INotifyPropertyChanged pattern
}

&#34;布尔&#34;类型:

public class BooleanEntry
{
    public bool Value { get; set; }  // Implement using standard INotifyPropertyChanged pattern
}

你说你想为每个条目类型设置一个标签,所以基类是个好主意:

public abstract class EntryBase
{
    public string Label { get; set; }  // Implement using standard INotifyPropertyChanged pattern
}

然后BooleanEntryPostalCodeEntry将来自EntryBase

Models 已排序。您只需要这些集合,以便可以从UI绑定它们。将适当的集合属性添加到Window ViewModel

public ObservableCollection<EntryBase> Entries { get; private set; }

在您的UI( View ,在XAML中实现)中,使用一个知道如何绑定到项目列表并将其可视化的控件实例。在WPF中,这将是ItemsControl或从ListBoxListView获取的控件:

<ItemsControl ItemsSource="{Binding Entries}" />

您可以看到我们如何将ItemsSource属性绑定到名为Entries的代码隐藏属性。 ItemsControl(及其后代)知道如何将这些项转换为可视化表示。默认情况下,您的自定义对象(在我们的示例中为EntryBase)将转换为字符串并显示为文本块。但是,通过使用data templates,您可以控制从对象到视觉的转换。

如果您将一些数据模板添加到资源部分,如下所示:

<Window ... xmlns:my="clr-namespace:---your namespace here---">
    <Window.Resources>
        <DataTemplate DataType="{x:Type my:PostalCodeEntry}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding Label}" />
                <TextBox Text="{Binding Value}" />
            </StackPanel>
        </DataTemplate>
        <DataTemplate DataType="{x:Type my:BooleanEntry}">
            <CheckBox Content="{Binding Label}" IsChecked="{Binding Value}" />
        </DataTemplate>
    </Window.Resources>

然后添加<ItemsControl ...元素,然后您应该会看到TextBlock类型的TextBox / PostalCodeEntry组合和CheckBox的{​​{1}}组合类型。

希望如果能够实现这一目标,它会让您了解如何扩展它以应对其他模型类型及其匹配的数据模板。