Associating a cell object property with a DataGridCell in a WPF DataGrid

Using WPF DataGrid, I need to change the various display and related properties of the DataGridCell - such as Foreground, FontStyle, IsEnabled, etc. - based on the corresponding property value of the cell object.

Now this is easy to do in code, for example (using the Observable Collection of ObservableDictionaries):

var b = new Binding("IsLocked") { Source = row[column], Converter = new BoolToFontStyleConverter() }; cell.SetBinding(Control.FontStyleProperty, b); 

and it works fine, however, I cannot figure out how to do this in XAML, since I cannot find a way to set the Path property of the cell object.

One XAML attempt:

 <Setter Property="FontStyle"> <Setter.Value> <MultiBinding Converter="{StaticResource IsLockedToFontStyleConverter}" Mode="OneWay" UpdateSourceTrigger="PropertyChanged"> <Binding /> <Binding RelativeSource="{x:Static RelativeSource.Self}"/> </MultiBinding> </Setter.Value> </Setter> 

but no binding to the IsLocked property

 public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { var row = (RowViewModel) values[0]; var cell = (DataGridCell) values[1]; if (cell != null && row != null) { var column = DataGridMethods.GetColumn(cell); return row[column].IsLocked ? "Italic" : "Normal"; } return DependencyProperty.UnsetValue; } 

Note that the previous version returned the string [col] .IsLocked and set FontStyle using a DataTrigger, but the returned object is not bound to the database.

Please note, of course, that the application does not know which columns are at design time.

Finally, DataTable is too inefficient for my requirements, but I would be interested to see how it is done with DataTables anyway, if there is such a solution for them, it can be useful elsewhere (although I prefer to use collections).

Of course, this is a common problem, and I'm a WPF newbie trying to transfer all MVVMs to my project, but this problem keeps me in regards to using DataGrid WPF.

+2
data-binding wpf mvvm datagrid datagridcell
source share
1 answer

Well, here is the simplest solution I have found. (In fact, I had this before I posted this and another question, but was in difficulty with such a solution. Since they did not hear anything here, and only in case someone faces the same problem, I thought I would share it.)

Put a reference to the cell object in the DataGridCell tag property. I do this using a combination of XAML and code binding inside the converter as follows:

  <Setter Property="Tag"> <Setter.Value> <MultiBinding Converter="{StaticResource CellViewModelToTagConverter}" Mode="OneWay" UpdateSourceTrigger="PropertyChanged"> <Binding /> <Binding RelativeSource="{x:Static RelativeSource.Self}"/> </MultiBinding> </Setter.Value> </Setter> 

and

  public class CellViewModelToTagConverter : IMultiValueConverter { public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) { var row = values[0] as RowViewModel; var cell = values[1] as DataGridCell; if (row != null && cell != null) { var column = DataGridMethods.GetColumn(cell); // hack within hack!!! (using tag way is itself a hack?) var b = new Binding("Self") {Source = row[column]}; cell.SetBinding(FrameworkElement.TagProperty, b); //... //return row[column]; return DependencyProperty.UnsetValue; } return DependencyProperty.UnsetValue; } public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) { throw new NotSupportedException(); } } 

You can say that I think of this solution with my comments inside the converter (I had to add the Self property to the Cell object and make Self = this in the constructor).

However, this allows you to fully encode Datagrid MVVM - if you agree that what I did inside the converter is consistent with MVVM. It works anyway!

Thus, I can see and manage everything that is in XAML, for example, to manage such a binding only in certain columns, placing XAML in the corresponding cellstyles (which does not do this through DataGrid.CellStyle).

In any case, an example of use

 <Style.Triggers> <DataTrigger Value="true" Binding="{Binding RelativeSource={RelativeSource Self}, Path=Tag.IsLocked}"> <Setter Property="FontStyle" Value="Italic"/> <Setter Property="IsEnabled" Value="False"/> </DataTrigger> </Style.Triggers> 

At the XAML level, it is simple and IMHO elegant (especially for various tooltips and pop-ups, for which I intensively use the properties of the cell object). However, I'm sure there is a better way to do this, is there?

Hope this all disappears when I can use Net 4.0 and dynamic objects, but for this project I can’t.

+4
source share

All Articles