I have a DataGrid that uses DataGridTemplateColumn to show the items of a collection. I used a template column because some items represent boolean values, some represent strings etc and I want different controls for the user to edit.
I can get the template column to show the proper control based upon the type of data in the collection but I am unable to make it actually update the underlying values when I edit them.
Meanwhile if I create a corresponding DataGridTextColumn to show the same values, that one will update the underlying string values every time. I can't figure out what I am doing wrong.
I've tested this by putting breakpoints on the "set" methods of the properties that I'm linking each column to. The TextColumn calls the set methods but the Template column does not.
What am I missing here?
Here's what the output looks like:
XAML:
<DataGrid ItemsSource="{Binding Path=Data}"
AutoGenerateColumns="False"
SelectionMode="Single"
VerticalScrollBarVisibility="Auto"
CanUserAddRows="False"
CanUserDeleteRows="False"
>
<DataGrid.Resources>
<DataTemplate DataType="{x:Type local:StringData}" x:Key="StringTemplate" >
<TextBox Text="{Binding ValueS, Mode=TwoWay}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:BoolData}" x:Key="BoolTemplate" >
<CheckBox IsChecked="{Binding ValueB, Mode=TwoWay}"/>
</DataTemplate>
<local:TemplateSelector x:Key="ParamSelector"
BoolTemplate="{StaticResource BoolTemplate}"
StringTemplate="{StaticResource StringTemplate}"/>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Name}" IsReadOnly="True"/>
<DataGridTextColumn Binding="{Binding Value}"/>
<DataGridTemplateColumn CellTemplateSelector="{StaticResource ParamSelector}"
CellEditingTemplateSelector="{StaticResource ParamSelector}"
MinWidth="80"/>
</DataGrid.Columns>
</DataGrid>
DataTypes stored in the collection:
public class BaseData
{
private String _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
private string _value;
public string Value
{
get { return _value; }
set { _value = value; }
}
}
public class BoolData : BaseData
{
private bool _bool;
public bool ValueB
{
get { return _bool; }
set { _bool = value; }
}
}
public class StringData : BaseData
{
private string _string;
public string ValueS
{
get { return _string; }
set { _string = value; }
}
}
And the collection of data from the ViewModel "Data" property:
public class MainVm : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
List<BaseData> _data;
public List<BaseData> Data
{
get
{
if (null == _data)
{
_data = new List<BaseData>();
_data.Add(new BoolData() { Name="FirstBool", Value="True", ValueB = true });
_data.Add(new StringData() { Name="FirstString", Value="Hello", ValueS = "Hello" });
_data.Add(new BoolData() { Name="SecondBool", Value="False", ValueB = false });
_data.Add(new StringData() { Name="SecondString", Value="Goodbye", ValueS = "Goodbye" });
_data.Add(new BoolData() { Name="ThirdBool", Value="True", ValueB = true });
}
return _data;
}
}
}
(I should mention: This example shows me using a CellEditingTemplateSelector that's the same as the CellTemplateSelector. I figured that made sense since the underlying template would be identical regardless. But I've also tried using a completely different editing selector and no editing selector but nothing helps.)