我有视图模型
public class ViewModel
{
public string TestField { get; set; }
public ObservableCollection<object> TestCollection { get; set; }
public ViewModel()
{
TestField = "ABCD";
}
}
我想根据 TestField 的值使用不同的 DataGridTemplateColumns。 DataGrid 将 TestCollection 作为其 ItemSource,并且在 DataTemplate 中,我想使用 ItemSource 中的项目。不过DataTemplate的选择需要依赖于TestField。 问题在于 TestField 位于 TestCollection 的上下文之外。
一种解决方案是使用转换器将 TestField 属性绑定到 CellTemplate 属性。
如果 TestField 属性在创建 ViewModel 实例后可以更改,则需要通过 INotifyPropertyChanged.PropertyChanged 事件提供其更改的通知。在我的示例中,这是通过 ViewModelBase 基类的方法完成的:
public class TestFieldViewModel : ViewModelBase
{
public string TestField { get => Get<string>(); set => Set(value); }
public ObservableCollection<object> TestCollection { get; /*set;*/ } = new();
public TestFieldViewModel()
{
foreach (var item in "Example")
{
TestCollection.Add(item);
}
// асинхронная смена значения с целью тестирования
Task.Run(async () =>
{
while (true)
{
await Task.Delay(2000);
TestField = TestField == "ABCD" ? string.Empty : "ABCD";
}
});
}
}
public class TestFieldTemplateConverter : IValueConverter
{
public DataTemplate Default { get; set; }
public DataTemplate ABCD { get; set; }
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return value switch
{
"ABCD" => ABCD,
_ => Default
};
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
<Window ----------------------------
----------------------------
DataContext="{DynamicResource vm}">
<Window.Resources>
<local:TestFieldViewModel x:Key="vm"/>
</Window.Resources>
<Grid>
<DataGrid ItemsSource="{Binding TestCollection}">
<DataGrid.Resources>
<DataTemplate x:Key="default">
<TextBlock Text="Default"/>
</DataTemplate>
<DataTemplate x:Key="ABCD">
<TextBlock Text="ABCD"/>
</DataTemplate>
<local:TestFieldTemplateConverter
x:Key="templateConverter"
Default="{StaticResource default}"
ABCD="{StaticResource ABCD}"/>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTemplateColumn
CellTemplate="{Binding TestField,
Source={StaticResource vm},
Converter={StaticResource templateConverter}}">
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>