为同一源定义不同的数据模板

本文关键字:数据 定义 | 更新日期: 2023-09-27 17:56:22

我正在尝试使用ListView的数据模板显示布尔值的集合。代码如下:

在 MainWindow.xaml 中

<Window.Resources>       
    <DataTemplate x:Key="ListItemCheckBoxTemplate">
        <CheckBox IsChecked="{Binding Mode=OneWay}"/>
    </DataTemplate>
    <DataTemplate x:Key="ListItemRadioButtonTemplate">
        <RadioButton IsChecked="{Binding Mode=OneWay}"/>
    </DataTemplate>
</Window.Resources>
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="120"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>        
    <TextBlock Text="ListViewSample" />
    <ListBox ItemsSource="{Binding MyData}" ItemTemplate="{StaticResource ListItemCheckBoxTemplate}" Grid.Column="1"/>                    
</Grid>

在 MainWindow.xaml 中.cs

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = new ViewModel();  
    }
}
public class ViewModel
{
    private List<bool> myBooleanCollection;
    public List<bool> MyData
    {
        get { return myBooleanCollection;  }
        set { myBooleanCollection = value; }
    }
    public ViewModel()
    {
        myBooleanCollection = new List<bool>();
        myBooleanCollection.Add(true);
        myBooleanCollection.Add(false);
        myBooleanCollection.Add(true);
        myBooleanCollection.Add(true);
        myBooleanCollection.Add(false);            
    }
}
而不是项目模板列表项目复选框模板,

我想应用带有单选按钮的列表项目单选按钮模板。如何在 xaml 中为同一源指定使用项模板。我是否需要更改相同或我是否有某种方法可以根据条件在 xaml 中指定数据模板。

为同一源定义不同的数据模板

您没有指定要更改模板的条件是什么,但您可以向视图模型添加另一个属性,例如AllowMultiple

public class ViewModel: INotifyPropertyChanged
{
   private List<bool> myBooleanCollection;
   public List<bool> MyData
   {
      get { return myBooleanCollection;  }
      set { myBooleanCollection = value; }
   }
   private bool _allowMultiple;
   public bool AllowMultiple
   {
      get { return _allowMultiple; }
      set
      {
         if (_allowMultiple != value)
         {
            _allowMultiple = value;
            OnPropertyChanged("AllowMultiple");
         }
      }
   }
}

,然后将ListBox.Style更改为:

<ListBox ItemsSource="{Binding MyData}">
   <ListBox.Style>
      <Style TargetType="{x:Type ListBox}">
         <Setter Property="ItemTemplate" Value="{StaticResource ListItemCheckBoxTemplate}"/>
         <Style.Triggers>
            <DataTrigger Binding="{Binding Path=AllowMultiple}" Value="False">
               <Setter Property="ItemTemplate" Value="{StaticResource ListItemRadioButtonTemplate}"/>
            </DataTrigger>
         </Style.Triggers>
      </Style>
   </ListBox.Style>
</ListBox>

假设ViewModel实现了INotifyPropertyChanged然后您可以更改ItemTemplate购买更改视图模型的更改AllowMultiple

您可以使用以下属性为每个项目指定 DataTemplate:

ItemTemplate="{StaticResource ListItemCheckBoxTemplate}

将其更改为:

ItemTemplate="{StaticResource ListItemRadioButtonTemplate}

如果需要在同一列表框中使用多个项模板,则可以通过 DataTemplateSelector 类提供自定义模板选择逻辑

如果要在 Xaml 中执行此操作,则需要公开可作为选择器绑定到的属性。查看 Xaml 中的数据模板选择器

您需要

创建DataTemplateSelector并将其用于ItemTemplateSelector。您还需要确定返回DataTemplate的条件。例:

XAML

<Window x:Class="YourNamespace.MainWindow" ...
        xmlns:this="clr-namespace:YourNamespace"
<Window.Resources>
    <DataTemplate x:Key="OneTemplate">
        <CheckBox IsChecked="{Binding Mode=OneWay}" />
    </DataTemplate>
    <DataTemplate x:Key="SecondTemplate">
        <RadioButton IsChecked="{Binding Mode=OneWay}" />
    </DataTemplate>
</Window.Resources>
<ListBox ItemsSource="{Binding MyData}">            
    <ListBox.ItemTemplateSelector>
        <this:MyItemTemplateSelector OneTemplate="{StaticResource OneTemplate}" 
                                     SecondTemplate="{StaticResource SecondTemplate}" />            
    </ListBox.ItemTemplateSelector>
</ListBox>

Code-behind

public class MyItemTemplateSelector : DataTemplateSelector
{
    public DataTemplate OneTemplate { get; set; }
    public DataTemplate SecondTemplate { get; set; }
    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        bool myItem = (bool)item;
        if (myItem == true)
        {
            return OneTemplate;
        }
        return SecondTemplate;
    }
}