【WPF】DataTemplateSelector的两个应用

宁睿  论坛元老 | 2025-4-17 09:51:51 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 1949|帖子 1949|积分 5857

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
数据模板选择器重要运用在一些项容器中用于根据差别的数据范例选择差别的DataTemplate,以便展示差别的数据。
核心是override重写SelectTemplate方法,以判断指定命据返回差别的模板。
同样的效果也可以直接使用DataTrigger控制Visibility属性实现,但是Selector更加优雅,维护性更好。
下面两种应用,使用两种差别的写法。
应用1:TreeView树目录差别层级差别模板

目录树实现的全部逻辑和动图效果检察此篇
共3个层级root,menu,detail,三个层级有差别的模板。因此在资源中定义三种HierarchicalDataTemplate控件模板,模板中为DataType赋值,这是使用Selector的关键;
DataType对应三个类名RootOrgNodeViewModel、MenuOrgNodeViewModel、DetailOrgNodeViewModel。都继续于OrgNodeViewModel。
  1. <HierarchicalDataTemplate x:Key="rootNodeTemplate"
  2. ItemsSource="{Binding Children}"
  3. DataType="{x:Type vm:RootOrgNodeViewModel}">
  4. <HierarchicalDataTemplate x:Key="menuNodeTemplate"
  5. ItemsSource="{Binding Children}"
  6. DataType="{x:Type vm:MenuOrgNodeViewModel}">
  7. <HierarchicalDataTemplate x:Key="detailNodeTemplate"
  8. ItemsSource="{Binding Children}"
  9. DataType="{x:Type vm:DetailOrgNodeViewModel}">
复制代码
资源中声明DataTemplateSelector选择器,并应用在TreeView中
  1. <LocalTmeplate:ContextMenuDataTemplateSelector
  2. x:Key="ContextMenuDataTemplateSelector"/>
  3. <TreeView Height="365" ItemsSource="{Binding Root}"
  4. ItemTemplateSelector="{StaticResource ContextMenuDataTemplateSelector}"/>
复制代码
完备xaml代码
  1. <UserControl .. x:Name="this">
  2.     <UserControl.Resources>
  3.         <vm:BindingProxy x:Key="Proxy" Data="{Binding}" />
  4.         <LocalTmeplate:ContextMenuDataTemplateSelector x:Key="ContextMenuDataTemplateSelector"/>
  5.         <ContextMenu x:Key="Tree_menuNodeMenu">
  6.             <MenuItem Name="Add" Command="{Binding Source={StaticResource Proxy}, Path=Data.AddNodeCommand}" CommandParameter="{Binding}">
  7.                 <MenuItem.Header>
  8.                     <StackPanel Orientation="Horizontal">
  9.                         <Label Content="新增"/>
  10.                         <TextBox Width="20" Text="{Binding Source={StaticResource Proxy}, Path=Data.AddCount}"
  11.                                  Height="20" HorizontalContentAlignment="Center" VerticalContentAlignment="Center"/>
  12.                         <Label Content="个子节点"/>
  13.                     </StackPanel>
  14.                 </MenuItem.Header>
  15.             </MenuItem>
  16.         </ContextMenu>
  17.         <ContextMenu x:Key="Tree_detailNodeMenu">
  18.             <MenuItem Header="删除" Name="Delete_self"
  19.                       Command="{Binding Source={StaticResource Proxy}, Path=Data.DeleteNodeCommand}" CommandParameter="{Binding}"/>
  20.             <Separator/>
  21.             <MenuItem Header="在上方插入" Name="Insert_up"
  22.                       Command="{Binding Source={StaticResource Proxy}, Path=Data.InsertBeforeNodeCommand}" CommandParameter="{Binding}"/>
  23.             <MenuItem Header="在下方插入" Name="Insert_down"
  24.                       Command="{Binding Source={StaticResource Proxy}, Path=Data.InsertAfterNodeCommand}" CommandParameter="{Binding}"/>
  25.             <Separator/>
  26.             <MenuItem Header="上移" Name="swap_up"
  27.                       Command="{Binding Source={StaticResource Proxy}, Path=Data.SwapBeforeNodeCommand}" CommandParameter="{Binding}"/>
  28.             <MenuItem Header="下移" Name="swap_down"
  29.                       Command="{Binding Source={StaticResource Proxy}, Path=Data.SwapAfterNodeCommand}" CommandParameter="{Binding}"/>
  30.         </ContextMenu>
  31.         <HierarchicalDataTemplate x:Key="menuNodeTemplate" ItemsSource="{Binding Children}" DataType="{x:Type vm:MenuOrgNodeViewModel}">
  32.             <StackPanel Orientation="Horizontal" ContextMenu="{StaticResource Tree_menuNodeMenu}">
  33.                 <Label Content="{Binding Name}"/>
  34.             </StackPanel>
  35.         </HierarchicalDataTemplate>
  36.         <HierarchicalDataTemplate x:Key="detailNodeTemplate" ItemsSource="{Binding Children}" DataType="{x:Type vm:DetailOrgNodeViewModel}">
  37.             <StackPanel Orientation="Horizontal" ContextMenu="{StaticResource Tree_detailNodeMenu}">
  38.                 <Label >
  39.                     <Label.Content>
  40.                         <TextBlock Text="{Binding Index,StringFormat={}[{0}号]}"/>
  41.                     </Label.Content>
  42.                 </Label>
  43.                 <Label Content="{Binding Name}"/>
  44.             </StackPanel>
  45.         </HierarchicalDataTemplate>
  46.         <HierarchicalDataTemplate x:Key="rootNodeTemplate" ItemsSource="{Binding Children}" DataType="{x:Type vm:RootOrgNodeViewModel}">
  47.             <StackPanel Orientation="Horizontal">
  48.                 <Label Content="{Binding Name}"/>
  49.             </StackPanel>
  50.         </HierarchicalDataTemplate>
  51.     </UserControl.Resources>
  52.     <StackPanel >
  53.         <TreeView Height="365" ItemsSource="{Binding Root}" ItemTemplateSelector="{StaticResource ContextMenuDataTemplateSelector}"/>
  54.     </StackPanel>
  55. </UserControl>
复制代码
定义Selector的逻辑
判断每个节点的范例,返回差别的模板
  1. public class ContextMenuDataTemplateSelector : DataTemplateSelector
  2. {
  3. //item表示TreeView数据源中每个Item
  4.     public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container)
  5.     {
  6.         FrameworkElement element = container as FrameworkElement;
  7.         DataTemplate template = null;
  8.         if (item is MenuOrgNodeViewModel)
  9.         {
  10.             template = element.FindResource("menuNodeTemplate") as HierarchicalDataTemplate;
  11.         }
  12.         else if (item is RootOrgNodeViewModel)
  13.         {
  14.             template = element.FindResource("rootNodeTemplate") as HierarchicalDataTemplate;
  15.         }
  16.         else if (item is DetailOrgNodeViewModel)
  17.         {
  18.             template = element.FindResource("detailNodeTemplate") as DataTemplate;
  19.         }
  20.         return template;
  21.     }
  22.    
  23. }
复制代码
定义每个节点对应的范例
  1. public class MenuOrgNodeViewModel : OrgNodeViewModel
  2. {
  3.      internal MenuOrgNodeViewModel(Node i, OrgNodeViewModel parent = null) : base(i, parent)
  4.      {
  5.      }
  6. }
  7. public class RootOrgNodeViewModel : OrgNodeViewModel
  8. {
  9.      internal RootOrgNodeViewModel(Node i, OrgNodeViewModel parent = null) : base(i, parent)
  10.      {
  11.      }
  12. }
  13. public class DetailOrgNodeViewModel : OrgNodeViewModel
  14. {
  15.      internal DetailOrgNodeViewModel(Node i, OrgNodeViewModel parent = null) : base(i, parent)
  16.      {
  17.      }
  18. }
复制代码
应用2:DataGrid表格单元格内使用差别模板

表格的全部逻辑和动图效果检察此篇,内含两种实现单元格编辑时为差别控件的方法
根据数据的范例单元格在编辑模式下,可以显示文本框、下拉框、弹窗按钮还有不可编辑单元格。
定义四种模板
  1. <local:CellEditTemplateSelector.TextBoxTemplate>
  2. <local:CellEditTemplateSelector.ComboxTemplate>
  3. <local:CellEditTemplateSelector.PopupButtonTemplate>
  4. <local:CellEditTemplateSelector.UnEnableTemplate>
复制代码
将选择器应用在表格所在列的CellEditingTemplateSelector上
  1. <local:CellEditTemplateSelector x:Key="CellEditTemplateSelector">
  2. <DataGridTemplateColumn Header="设定值"
  3. CellEditingTemplateSelector="{StaticResource CellEditTemplateSelector}">
复制代码
选择器相干的关键xaml代码
  1. <UserControl.Resources>
  2.         <local:SetValueTextEditingConverter x:Key="SetValueTextEditingConverter"/>
  3.         <local:CellEditTemplateSelector x:Key="CellEditTemplateSelector">
  4.                 <local:CellEditTemplateSelector.TextBoxTemplate>
  5.                         <DataTemplate>
  6.                                 <TextBox>
  7.                                         <TextBox.Text>
  8.                                                 <MultiBinding Converter="{StaticResource SetValueTextEditingConverter}">
  9.                                                         <Binding Path="setValue" UpdateSourceTrigger="PropertyChanged" />
  10.                                                         <Binding Path="decimalPlaces"/>
  11.                                                 </MultiBinding>
  12.                                         </TextBox.Text>
  13.                                 </TextBox>
  14.                         </DataTemplate>
  15.                 </local:CellEditTemplateSelector.TextBoxTemplate>
  16.                 <local:CellEditTemplateSelector.ComboxTemplate>
  17.                         <DataTemplate>
  18.                                 <ComboBox ItemsSource="{Binding valueOptions}"
  19.                                                                           SelectedItem="{Binding selectedOptionItem}">
  20.                                         <ComboBox.ItemTemplate>
  21.                                                 <DataTemplate>
  22.                                                         <TextBlock Text="{Binding fullDetail}"/>
  23.                                                 </DataTemplate>
  24.                                         </ComboBox.ItemTemplate>
  25.                                 </ComboBox>
  26.                         </DataTemplate>
  27.                 </local:CellEditTemplateSelector.ComboxTemplate>
  28.                 <local:CellEditTemplateSelector.PopupButtonTemplate>
  29.                         <DataTemplate>
  30.                                 <Grid>
  31.                                         <TextBlock Text="{Binding setValue,Mode=TwoWay}"/>
  32.                                         <Button Width="20" Content="..." HorizontalAlignment="Right"
  33.                                                         Command="{Binding EditChildValueCommand}"
  34.                                                         CommandParameter="{Binding}"/>
  35.                                 </Grid>
  36.                         </DataTemplate>
  37.                 </local:CellEditTemplateSelector.PopupButtonTemplate>
  38.                 <local:CellEditTemplateSelector.UnEnableTemplate>
  39.                         <DataTemplate>
  40.                                 <TextBlock Text="--"/>
  41.                         </DataTemplate>
  42.                 </local:CellEditTemplateSelector.UnEnableTemplate>
  43.         </local:CellEditTemplateSelector>
  44. ...
  45.         <DataGridTemplateColumn Header="设定值" CellEditingTemplateSelector="{StaticResource CellEditTemplateSelector}">
  46.                 <DataGridTemplateColumn.CellTemplate>
  47.                         <DataTemplate>
  48.                                 ...
  49.                         </DataTemplate>
  50.                 </DataGridTemplateColumn.CellTemplate>
  51.         </DataGridTemplateColumn>
  52. </UserControl.Resources>
复制代码
选择器逻辑
  1. public class CellEditTemplateSelector : DataTemplateSelector
  2. {
  3.         public DataTemplate TextBoxTemplate { get; set; }
  4.         public DataTemplate ComboxTemplate { get; set; }
  5.         public DataTemplate PopupButtonTemplate { get; set; }
  6.         public DataTemplate UnEnableTemplate { get; set; }
  7.         public override System.Windows.DataTemplate SelectTemplate(object item, System.Windows.DependencyObject container) {
  8.         //item为表格每行数据源,选择模板的关键是判断数据源中editType和valueType两个属性值
  9.                 if (item is GirdDataModel) {
  10.                         GirdDataModel data = item as GirdDataModel;
  11.                         if (data.editType == "不可修改") return UnEnableTemplate;
  12.                         switch (data.valueType)
  13.                         {
  14.                                 case ValueTypeEnum.Number:
  15.                                         return TextBoxTemplate;
  16.                                 case ValueTypeEnum.Option:
  17.                                         return ComboxTemplate;
  18.                                 case ValueTypeEnum.Object:
  19.                                         return PopupButtonTemplate;
  20.                         }
  21.                 }
  22.                 return base.SelectTemplate(item, container);
  23.         }
  24. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

宁睿

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表