问题描述
使用WPF DataGrid我需要根据单元对象属性的相关值来更改DataGridCell的各种显示和相关属性,例如Foreground,FontStyle,IsEnabled等。
Using the WPF DataGrid I have the need to change various display and related properties of a DataGridCell - such as Foreground, FontStyle, IsEnabled and so on - based on the relevant value of the cell object property.
现在,这很容易在代码中使用,例如(使用Observable Collection of ObservableDictionaries):
Now this is easy to do in code, for example (using an Observable Collection of ObservableDictionaries):
var b = new Binding("IsLocked") { Source = row[column], Converter = new BoolToFontStyleConverter() };
cell.SetBinding(Control.FontStyleProperty, b);
并且工作正常,但是我无法看到如何在XAML中执行此操作,因为我无法找到将路径设置为单元对象的属性。
and works fine, however I cannot see how to do this in XAML since I can find no way to set Path to a cell object's property.
一个XAML尝试是:
<Setter Property="FontStyle">
<Setter.Value>
<MultiBinding Converter="{StaticResource IsLockedToFontStyleConverter}" Mode="OneWay" UpdateSourceTrigger="PropertyChanged">
<Binding />
<Binding RelativeSource="{x:Static RelativeSource.Self}"/>
</MultiBinding>
</Setter.Value>
</Setter>
但是没有绑定到 IsLocked 属性
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;
}
请注意,以前的版本返回行[col] .IsLocked 并使用DataTrigger设置FontStyle,但返回的对象不是数据绑定的。
Please note that a previous version returned row[col].IsLocked and set the FontStyle using a DataTrigger but a returned object is not databound.
当然,应用程序不知道这些列在设计时是什么。
Note, of course, that the application does not know what the columns are at design time.
最后,DataTable对我的要求太低效,但是我有兴趣看看DataTable如何完成,如果有这样的解决方案,这可能在其他地方有用(尽管我喜欢使用集合)。
Finally DataTable's are far too inefficient for my requirements but I would be interested to see how this is done with DataTables anyway, if there is such a solution for them, this might be useful elsewhere (although I prefer using collections).
当然这是一个常见问题,我是一个WPF noobie试图去我的项目的所有MVVM,但这个问题正在抱着我使用WPF DataGrid。
Surely this is a common issue and I am a WPF noobie trying to go all MVVM on my project, but this issue is holding me back with respect to using the WPF DataGrid.
推荐答案
这里是我找到的最简单的解决方案。 (实际上我在发布这个和另一个问题之前就这样解决了这个问题,因为在这里听不到任何其他的东西,只要有人遇到同样的问题,我想我会分享一下。)
Well here is the simplest solution I have found. (Actually I had it before I posted this and the other question but was embarrased at such a solution.Since have heard nothing else here and just it is in case anyone else is faced with the same problem, I thought I would share it.)
在DataGridCell标签属性中引用单元格对象。我用XAML和转换器中的代码绑定的组合如下所示:
Put a reference to the cell object in the DataGridCell Tag property. I do this with a combination of XAML and a code binding inside a 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>
和
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();
}
}
你可以通过我的转换器中的注释(我不得不在Cell对象中添加一个Self属性,并在构造函数中使Self = this)。
You can tell what I think of this solution by my comments inside the converter.(I had to add a Self property to the Cell object and make Self=this in the constructor).
仍然使我的Datagrid编码成为完全是MVVM - 如果你接受我在转换器内部所做的一切与MVVM一致。无论如何,它的工作原理!
Still it enables my Datagrid coding to be entirely MVVM - if you accept that what I have done inside the converter is consistent with MVVM. Anyway it works!
所以这样做,我可以看到和管理从XAML的一切,例如通过将XAML放在相关列的cellstyles (这不是通过DataGrid.CellStyle这样做的)。
So doing it this way I can see and manage everything from XAML such as control such binding only on certain columns by placing the XAML within the relevant column cellstyles (that is not doing this via DataGrid.CellStyle).
无论如何,使用的一个例子是
Anyway, an example of usage is
<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>
在XAML层面上,它既简单又优雅(特别适用于各种工具提示和弹出窗口)大量使用单元格对象的属性)。但是,我确信有更好的方法来做,是吗?
On the XAML level it is both simple and IMHO elegant (especially for various ToolTips and Popups for which I make heavy usage of cell object's properties). However I am sure there is a better way of doing this, is there?
希望这些都可以使用Net 4.0和动态对象,但对于这个项目我不能。
Hopefully this all goes away when I can use Net 4.0 and dynamic objects, but for this project I cannot.
这篇关于将单元对象的属性绑定到WPF DataGrid中的DataGridCell的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!