I have ViewModel
public class ViewModel
{
public string TestField { get; set; }
public ObservableCollection<object> TestCollection { get; set; }
public ViewModel()
{
TestField = "ABCD";
}
}
I want to use different DataGridTemplateColumns depending on the value of TestField. The DataGrid will have TestCollection as its ItemSource, and within the DataTemplate, I want to use an item from the ItemSource. However, the choice of DataTemplate needs to depend on TestField. The issue is that TestField is outside the context of TestCollection.
One solution is to use a converter to bind the TestField property to the CellTemplate property.
If the TestField property can change after the ViewModel instance is created, then it is necessary to provide notification of its change through the INotifyPropertyChanged.PropertyChanged event. In my example, this is done through the methods of the ViewModelBase base class:
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 = "ABCD";
await Task.Delay(2000);
TestField = string.Empty;
}
});
}
}
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>