WinUI3 DataGrid中DataTemplateSelector.SelectTemplateCore未执行问题排查
WinUI 3 DataGrid DataTemplateSelector 不执行的问题解决
问题场景
在WinUI3中搭建简易DataGrid,要求第二列根据CFieldValue的数据类型渲染不同控件:布尔值显示CheckBox,字符串显示TextBox。通过继承DataTemplateSelector实现了自定义选择器DataTemplateSelectorExt,但重写的SelectTemplateCore方法完全不触发,第二列仅显示CustomInfo类的命名空间。
问题原因
- 缺少必要的方法重载:WinUI3的
DataGrid调用DataTemplateSelector时,会使用带DependencyObject参数的SelectTemplateCore重载,仅实现object item参数的版本不会被调用。 - GridTemplateColumn绑定配置错误:只设置
MappingName无法让选择器正确获取CFieldValue的值,需要明确指定模板的绑定目标。 - DataTemplate的x:DataType冲突:模板中指定了
x:DataType,但CFieldValue是object类型,x:Bind无法自动解析实际类型,导致绑定失效。
解决步骤及修改后代码
1. 修正DataTemplateSelector的方法实现
补充带DependencyObject参数的重载方法,确保DataGrid能正确调用选择逻辑:
public class DataTemplateSelectorExt : DataTemplateSelector { public DataTemplate TextBlockTemplate { get; set; } public DataTemplate TextBoxTemplate { get; set; } public DataTemplate CheckBoxTemplate { get; set; } // WinUI3 DataGrid会调用这个重载 protected override DataTemplate SelectTemplateCore(object item, DependencyObject container) { return SelectTemplateCore(item); } protected override DataTemplate SelectTemplateCore(object item) { if (item == null) { return TextBlockTemplate; } else if (item is string) { return TextBoxTemplate; } else if (item is bool) { return CheckBoxTemplate; } else { return TextBlockTemplate; } } }
2. 调整XAML中的DataGrid列配置
通过ContentPresenter明确绑定到CFieldValue,并指定ContentTemplateSelector,替换原有的GridTemplateColumn直接设置CellTemplateSelector的方式:
<Page.Resources> <local:DataTemplateSelectorExt x:Key="templateselctor" CheckBoxTemplate="{StaticResource CheckBoxTemplateResource}" TextBlockTemplate="{StaticResource TextBlockTemplateResource}" TextBoxTemplate="{StaticResource TextBoxTemplateResource}" /> <DataTemplate x:Key="TextBlockTemplateResource"> <Grid> <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding}" /> </Grid> </DataTemplate> <DataTemplate x:Key="TextBoxTemplateResource"> <Grid> <TextBox Text="{Binding Mode=TwoWay}" /> </Grid> </DataTemplate> <DataTemplate x:Key="CheckBoxTemplateResource"> <Grid> <CheckBox HorizontalAlignment="Center" VerticalAlignment="Center" IsChecked="{Binding Mode=TwoWay}" /> </Grid> </DataTemplate> </Page.Resources> <Grid> <DataGrid x:Name="dataGrid1" ItemsSource="{x:Bind ViewModel.CustomInfoItems}"> <DataGrid.Columns> <GridTextColumn MappingName="CFieldDisplayName" /> <GridTemplateColumn Header="Field Value"> <GridTemplateColumn.CellTemplate> <DataTemplate> <!-- 绑定到CustomInfo的CFieldValue属性,再用选择器选模板 --> <ContentPresenter Content="{Binding CFieldValue}" ContentTemplateSelector="{StaticResource templateselctor}" /> </DataTemplate> </GridTemplateColumn.CellTemplate> </GridTemplateColumn> </DataGrid.Columns> </DataGrid> </Grid>
3. 移除DataTemplate的x:DataType
因为CFieldValue是object类型,x:DataType会限制绑定的类型解析,直接使用{Binding}即可适配不同数据类型。
验证效果
修改完成后,SelectTemplateCore方法会被正常触发,第二列会根据CFieldValue的类型分别渲染TextBox或CheckBox,不再显示命名空间。
内容的提问来源于stack exchange,提问作者E. A. Bagby
相关产品推荐
相关产品推荐

