首页 文章

将单元对象的属性绑定到WPF DataGrid中的DataGridCell

提问于
浏览
2

使用WPF DataGrid我需要根据单元格对象属性的相关值更改DataGridCell的各种显示和相关属性 - 例如Foreground,FontStyle,IsEnabled等 .

现在这在代码中很容易做到(例如(使用ObservableDictionaries的Observable Collection):

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

并且工作正常,但我无法在XAML中看到如何执行此操作,因为我无法将 Path 设置为单元对象的属性 .

一个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;
}

请注意,先前版本返回row [col] .IsLocked并使用DataTrigger设置FontStyle,但返回的对象不是数据绑定 .

当然,请注意,应用程序不知道列在设计时是什么 .

最后,DataTable对我的要求来说效率太低了,但我很想知道如何使用DataTables完成这项工作,如果有这样的解决方案,这可能在其他地方很有用(尽管我更喜欢使用集合) .

当然这是一个常见问题,我是一个WPF noobie试图在我的项目中使用所有MVVM,但是这个问题让我对使用WPF DataGrid感到不满 .

1 回答

  • 4

    那么这是我找到的最简单的解决方案 . (事实上,在我发布此问题和其他问题之前我已经有了这个问题,但是在这样的解决方案上很尴尬 . 因为在这里没有听到任何其他内容,只是为了防止其他人面临同样的问题,我想我会分享它 . )

    在DataGridCell Tag属性中引用单元格对象 . 我使用XAML和转换器内部的代码绑定组合执行此操作,如下所示:

    <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) .

    它仍然使我的Datagrid编码完全是MVVM - 如果你接受我在转换器内所做的事情与MVVM一致 . 无论如何它有效!

    这样做我可以通过XAML查看和管理所有内容,例如通过将XAML放在相关的列单元格样式中来控制这种绑定(通过DataGrid.CellStyle不这样做) .

    无论如何,使用的一个例子是

    <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级别上,它既简单又恕我直言(特别是对于我大量使用单元对象属性的各种工具提示和弹出窗口) . 但是我确信有更好的方法可以做到这一点,是吗?

    当我可以使用Net 4.0和动态对象时,希望这一切都消失了,但对于这个项目我不能 .

相关问题