Reputation: 6166
I have a property grid control that has many cell editors that automatically gets applied using a CellEditorTemplateSelector
. Each property grid row is bound against a simple PropertyItemViewModel.
Now, I'm trying to reuse all these cell editors and present it in a DataGrid to be able to compare multiple object values side by side. So I added a PropertiesRow
object that contains a list of PropertyItemViewModel
(same as the above property grid).
To present each cell, I have a simple data template that uses the same template selector as the property grid.
<DataTemplate x:Key="CellDataTemplate">
<ContentControl
Content="{Binding Mode=OneWay}"
ContentTemplateSelector="{StaticResource CellEditorTemplateSelector}" />
</DataTemplate>
However, for this to work, the template expects a PropertyItemViewModel
(not the PropertiesRow), so I have to somehow feed it through a binding that fetches the correct one from PropertiesRow.PropertyItems[columnIndex]
. So when I add the columns through the code, I tried something like this:
void AddColumns()
{
foreach (Property shownProperty in _ShownProperties)
{
_DataGrid.Columns.Add(new DataGridTemplateColumn()
{
Header = shownProperty.Name;
Binding = new Binding("PropertyItems[" + index + "]");
CellTemplate = (DataTemplate) FindResource("CellDataTemplate");
});
}
}
However, DataGridTemplateColumn
does not have a Binding property! So I tried to generate an intermediate DataTemplate for each column, but that is starting to be very complex, and I feel there must be a simpler way of doing this.
Any suggestions?
Upvotes: 0
Views: 2081
Reputation: 21
I was having trouble with the XAML above but I got this to work. Had to set Path=''
or the compiler was unhappy.
Content="{Binding Mode=OneWay, Path='',
RelativeSource={RelativeSource FindAncestor, AncestorType=DataGridCell,
AncestorLevel=1},
Converter={StaticResource CellToColumnValueConverter}}"
Upvotes: 2
Reputation: 6166
I found a way to do it, which is not clean by MVVM standards because it plays with the DataGridCells directly, but it works fine otherwise.
I left my cell template as is, except instead of leaving it bound to my PropertiesRow object, which has no indication of which column we are in, I bind using a relative source binding to the parent DataGridCell:
<DataTemplate x:Key="CellDataTemplate">
<ContentControl
Content="{Binding Mode=OneWay,
RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type Controls:DataGridCell}},
Converter={StaticResource CellToColumnValueConverter}}}"
ContentTemplateSelector="{StaticResource CellEditorTemplateSelector}" />
</DataTemplate>
I then added a CellToColumnValueConverter
which takes the DataGridCell and transforms it into a PropertyItem using the index of the column:
public class CellToColumnValueConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
DataGridCell cell = (DataGridCell) value;
int displayIndex = cell.Column.DisplayIndex;
PropertiesRow r = (PropertiesRow) cell.DataContext;
return r.PropertyItems[displayIndex];
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Upvotes: 0