设置DataContext之后的DataTemplate选择器 [英] DataTemplate Selector after DataContext Set
问题描述
我有2列的DataGrid。基于绑定到ParameterDataType的第一列,我想在第二列中加载适当的模板。
I have a DataGrid with 2 columns. Based on the first column which is bound to ParameterDataType I want to load the appropriate template in the second column.
此代码的问题是在加载DataGrid之前,模板选择器正在执行,因此该项目为null。设置ControlTemplate的DataContext之后,是否可以执行模板选择器。请帮忙。
Problem with this code is before the DataGrid has been loaded, the template selector is executing as a result the item is null. Is there a way to execute the Template Selector after the ControlTemplate's DataContext is set. Please help.
这是我的xaml:
<uwpControls:DataGrid Grid.Row="4"
ItemsSource="{x:Bind ViewModel.ServiceMethodsData,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
AutoGenerateColumns="False">
<uwpControls:DataGrid.Resources>
<DataTemplate x:Key="StringTemplate">
<TextBox Width="150" Height="30" VerticalAlignment="Center"></TextBox>
</DataTemplate>
<DataTemplate x:Key="IntegerTemplate">
<controls:TextBoxNumeric Width="150" Height="30" VerticalAlignment="Center"></controls:TextBoxNumeric>
</DataTemplate>
<DataTemplate x:Key="BooleanTemplate">
<CheckBox IsChecked="False"></CheckBox>
</DataTemplate>
<local:MethodValueDataTemplateSelector x:Key="MethodValueTemplateSelector"
StringTemplate="{StaticResource StringTemplate}"
IntegerTemplate="{StaticResource IntegerTemplate}"
BooleanTemplate="{StaticResource BooleanTemplate}"/>
</uwpControls:DataGrid.Resources>
<uwpControls:DataGrid.Columns>
<uwpControls:DataGridTextColumn Header="First Column"
Binding="{Binding ParameterDataType, Mode=OneWay}"/>
<uwpControls:DataGridTemplateColumn Header="Second Column">
<uwpControls:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ContentControl x:Name="MethodValueContentControl"
Content="{Binding Path=.}"
ContentTemplateSelector="{StaticResource MethodValueTemplateSelector}"></ContentControl>
</DataTemplate>
</uwpControls:DataGridTemplateColumn.CellTemplate>
</uwpControls:DataGridTemplateColumn>
</uwpControls:DataGrid.Columns>
</uwpControls:DataGrid>
这是我的DataTemplate选择器
Here is my DataTemplate selector
public class MethodValueDataTemplateSelector : DataTemplateSelector
{
public DataTemplate StringTemplate { get; set; }
public DataTemplate IntegerTemplate { get; set; }
public DataTemplate BooleanTemplate { get; set; }
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
//I want to do something like if(DataContext.ParameterDataType=="Int") return IntegerTemplate etc
return StringTemplate;
}
}
这是我的ViewModel
Here is my ViewModel
public class ServiceUtilityMethodsViewModel
{
private ObservableCollection<VmServiceMethodsViewDataGridModel> _serviceMethodsData;
public ObservableCollection<VmServiceMethodsViewDataGridModel> ServiceMethodsData
{
get => _serviceMethodsData;
set => Set(ref _serviceMethodsData, value);
}
public ServiceUtilityMethodsViewModel(INavigationService navigationService) : base(navigationService)
{
PopulateServiceData();
}
private void PopulateServiceData()
{
ServiceMethodsData = new ObservableCollection<VmServiceMethodsViewDataGridModel>();
ServiceMethodsData.Add(new VmServiceMethodsViewDataGridModel()
{
ParameterName = "Param1",
ParameterDataType = "String"
});
ServiceMethodsData.Add(new VmServiceMethodsViewDataGridModel()
{
ParameterName = "Param2",
ParameterDataType = "Int"
});
ServiceMethodsData.Add(new VmServiceMethodsViewDataGridModel()
{
ParameterName = "Param3",
ParameterDataType = "bool"
});
}
}
}
这是我的模型课程
public class VmServiceMethodsViewDataGridModel : BindableBaseThreadSafe
{
private string _parameterName;
private string _parameterDataType;
public string ParameterName
{
get => _parameterName;
set => Set(ref _parameterName, value);
}
public string ParameterDataType //I want the template selector to work based on this column.
{
get => _parameterDataType;
set => Set(ref _parameterDataType, value);
}
}
推荐答案
您应该将 DataTemplateSelector
分配给 DataGridTemplateColumn.CellTemplateSelector
和 DataGridTemplateColumn.CellEditingTemplateSelector
直接。
You should assign the DataTemplateSelector
to DataGridTemplateColumn.CellTemplateSelector
and DataGridTemplateColumn.CellEditingTemplateSelector
directly.
我没有检查UWP版本。我认为UWP DataGridTemplateColumn
没有此模板选择器属性。在这种情况下,您可以坚持使用当前的XAML,但也不要忘记定义 CellEditingTemplate
(例如,替换 TextBlock
带有 TextBox
的 CellEditingTemplate
版本-最好使用 TextBlock
在您的默认 CellTemplate
中,因为它看起来更好)。在UWP版本中肯定会存在属性 CellTemplate
和 CellEditingTemplate
。
I didn't check the UWP version. I think the UWP DataGridTemplateColumn
doesn't have this template selector properties. In this case you can stick to your current XAML, but don't forget to define a CellEditingTemplate
too (e.g., replace the TextBlock
with a TextBox
for the CellEditingTemplate
version - better use a TextBlock
in your default CellTemplate
as it looks better). The properties CellTemplate
and CellEditingTemplate
exist for sure in the UWP version.
XAML DataGrid
定义
XAML DataGrid
definition
<uwpControls:DataGrid ItemsSource="{x:Bind ViewModel.ServiceMethodsData,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
AutoGenerateColumns="False">
<uwpControls:DataGrid.Resources>
<DataTemplate x:Key="StringTemplate">
<TextBox Width="150" Height="30" VerticalAlignment="Center" />
</DataTemplate>
<DataTemplate x:Key="IntegerTemplate">
<controls:TextBoxNumeric Width="150" Height="30" VerticalAlignment="Center" />
</DataTemplate>
<DataTemplate x:Key="BooleanTemplate">
<CheckBox IsChecked="False" />
</DataTemplate>
<local:MethodValueDataTemplateSelector x:Key="MethodValueTemplateSelector"
StringTemplate="{StaticResource StringTemplate}"
IntegerTemplate="{StaticResource IntegerTemplate}"
BooleanTemplate="{StaticResource BooleanTemplate}" />
</uwpControls:DataGrid.Resources>
<uwpControls:DataGrid.Columns>
<uwpControls:DataGridTextColumn Header="First Column"
Binding="{Binding ParameterDataType, Mode=OneWay}" />
<uwpControls:DataGridTemplateColumn Header="Second Column"
CellTemplateSelector="{StaticResource MethodValueTemplateSelector}"
CellEditingTemplateSelector="{StaticResource MethodValueTemplateSelector}">
</uwpControls:DataGridTemplateColumn>
</uwpControls:DataGrid.Columns>
</uwpControls:DataGrid>
DataTemplateSelector
也非常简单。 br>
SelectTemplateCore
覆盖的参数是项目和项目的容器(这是 FrameWorkElement
和 ContentControl
大部分时间)。
该项目始终是数据模型,而 DataContext $ c $当前行的c>。在您的情况下,该项目的类型为
VmServiceMethodsViewDataGridModel
。
The DataTemplateSelector
is also quite simple.
The parameters of the SelectTemplateCore
override are the item and the item's container (which is a FrameWorkElement
and a ContentControl
most of the time).
The item is always the data model and the DataContext
of the current row. In your case the item is of type VmServiceMethodsViewDataGridModel
.
容器是 FrameWorkElement
,用于包装模型以进行渲染,例如 ListBoxItem
。在您的情况下,容器的类型应为 DataGridRow
。
The container is the FrameWorkElement
that wraps the model for rendering e.g. ListBoxItem
. In your case the container should be of type DataGridRow
.
只需将item参数转换为适当的类型并求值
Simply cast the item parameter to the appropriate type and evaluate it.
MethodValueDataTemplateSelector.cs
public class MethodValueDataTemplateSelector : DataTemplateSelector
{
public DataTemplate StringTemplate { get; set; }
public DataTemplate IntegerTemplate { get; set; }
public DataTemplate BooleanTemplate { get; set; }
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
// Return if the control is not loaded yet and the item is therefore null
// or the item is of the wrong type
if (!(item is VmServiceMethodsViewDataGridModel dataModel))
{
return null;
}
// I want to do something like:
// if(DataContext.ParameterDataType=="Int") return IntegerTemplate etc
switch (dataModel.ParameterDataType)
{
case string value when value.Equals("Int", StringComparison.OrdinalIgnoreCase):
return IntegerTemplate;
case string value when value.Equals("String", StringComparison.OrdinalIgnoreCase):
return StringTemplate;
case string value when value.Equals("Bool", StringComparison.OrdinalIgnoreCase):
return BooleanTemplate;
default:
return null;
}
}
}
这篇关于设置DataContext之后的DataTemplate选择器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!