根据价值变动细胞 - WPF的DataGrid结构 [英] Structure of WPF DataGrid - change cells depending on value

查看:137
本文介绍了根据价值变动细胞 - WPF的DataGrid结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我做了一个对象绑定到 DataGridTextColumn 并想引用其属性之一从相应CellStyle内。我认为此列的每个单元将包含为MyObject 的一个实例。不过,我不能在 DataGridCell (我用一个简单的转换器来设置一个断点,并搜查了 DataGridCell <找到对象的引用/ code> -object相当长一段时间)。

I did bind an Object to a DataGridTextColumn and would like to reference one of its properties from within the corresponding CellStyle. I assumed that each cell of this column would contain an instance of MyObject. However I can't find a reference to the Object from within the DataGridCell (I used a trivial converter to set a break point and searched the DataGridCell-object for quite a while).

我找物业MyObject.IsEnabled并想引用的路径 - 属性指出在下面的代码的 ??? 的。任何建议

I am looking for the Property MyObject.IsEnabled and would like to reference that in the Path-Property noted with ??? in the code below. Any suggestions?

<DataGridTextColumn Binding="{Binding MyObject}">
    <DataGridTextColumn.CellStyle>
        <Style TargetType="DataGridCell">
            <Style.Triggers>
                <DataTrigger Path="???" Binding="{Binding RelativeSource={RelativeSource Self}, PresentationTraceSources.TraceLevel=High,Converter={StaticResource debugger}}"  Value="False">
                    <!-- some setters -->
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </DataGridTextColumn.CellStyle>
</DataGridTextColumn>



编辑:

因为我想这种风格应用到我的DataGrid后的所有细胞上有必要发现它是通过的RelativeSource 绑定到单元格的对象,而不是添加硬编码结合为MyObject

Since i want to apply this style to all Cells of my DataGrid later on it is essential to find the object which is bound to the cell via RelativeSource instead of adding a hardcoded binding to MyObject.

SOLUTION

由于antiocol我能找到我的情况下,这可能能够适合于类似的问题的解决方案的投入。

Thanks to the input of antiocol i was able to find a solution for my case which possibly can be adapted to similar problems.

既然问题是我们没有进入到Cell的值或 CellModel 从内部 CellStyle ,我们使用一个对附加属性的 DataGridCell 整个 CellModel 存储在那里。从那里,我们可以绑定任何访问属性 DataGridCell 我们的 CellModel

Since the problem is that we don't have access to the values of the Cell or a CellModel from within the CellStyle, we use an attached Property on the DataGridCell to store the whole CellModel in there. From there we can bind any accessible Property of the DataGridCell to any Property of our CellModel.

有关附加属性的代码:

public static class DataGridUtils
{
public static CellModel GetCellModel(DependencyObject obj)
{
    return (CellModel)obj.GetValue(CellModelProperty);
}
public static void SetCellModel(DependencyObject obj, CellModel value)
{
    obj.SetValue(CellModelProperty, value);
}
public static readonly DependencyProperty CellModelProperty =
    DependencyProperty.RegisterAttached("CellModel", typeof(CellModel), typeof(DataGridUtils), new UIPropertyMetadata(null));

我们需要设置我们的DataGrid的每一个细胞此属性。我没有找到一个好的解决办法在XAML中要做到这一点,所以现在我将它在转换器之前,我检索信息。 (改进的建议表示赞赏)

We need to set this property on every cell in our DataGrid. I didn't find a good solution to do this in XAML, so for now I set it in the converter before I retrieve the information. (suggestions for improvement appreciated)

转换器:

public class CellToEnabledConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        var cell = values[0] as DataGridCell;
        DataGridTextColumn column = cell.Column as DataGridTextColumn;
        //you should probably check if column is null after casting.
        Binding b = column.Binding as Binding;

        //Any suggestions on how to create a Binding to the parent object properly? 
        //I needed this workaround since I bind `MyObject.Value` to the `DataGridTextColumn`, 
        //but need a reference to `MyObject` here.
        Binding b1 = new Binding(b.Path.Path.Split('.')[0]){ Source = cell.DataContext };

        cell.SetBinding(DataGridUtils.CellModelProperty, b1);
        CellModel c = DataGridUtils.GetCellModel(cell);

        return c.IsEnabled;
    }

现在,我们可以定义一个全局风格在XAML并将其应用到整个的DataGrid 而不是单个列。

Now we can define a global Style in XAML and apply it to the whole DataGrid instead of a single column.

<Window.Resources>
    <converter:CellToEnabledConverter x:Key="CellToEnabledConverter" />

    <Style x:Key="DataGridCellStyle" TargetType="DataGridCell">
        <Style.Triggers>
            <DataTrigger Value="False">
                <DataTrigger.Binding>
                    <!--This Converter works only on DataGridTextColumns with this minimal example!-->
                    <Binding Converter="{StaticResource CellToEnabledConverter}">
                        <Binding RelativeSource="{RelativeSource Self}" />
                    </Binding>
                </DataTrigger.Binding>
                <!--Setters-->
            </DataTrigger>
        </Style.Triggers>
    </Style>
</Window.Resources>

<DataGrid CellStyle="{StaticResource DataGridCellStyle}">
    <DataGridTextColumn Binding="{Binding MyObject.Value}"/>
</DataGrid>



由于我发现在网上指出一些意见认为造型根据其值只是一个单元格不可能与当前的的DataGrid ,我希望这种解决方法可以帮助别人了。

Since i found several comments on the net stating that "styling a cell depending on its value just is not possible with the current DataGrid", i hope this workaround helps someone out.

推荐答案

我一直在试图为你的问题的另一个解决方案

I have been trying another solution for your problem.

<Style x:Key="DataGridCellStyle" TargetType="{x:Type DataGridCell}">
    <Style.Triggers>
        <DataTrigger Binding="{Binding Path=., RelativeSource={RelativeSource Self},  Converter={StaticResource DataGridCellToBooleanConverter}, ConverterParameter=IsEnabled}" Value="True">
            <Setter Property="Background" Value="Yellow"/>
        </DataTrigger>
    </Style.Triggers>
</Style>

<DataGrid CellStyle="{StaticResource DataGridCellStyle}">
   <DataGrid.Columns>
        <DataGridTextColumn Header="MyObject1" Binding="{Binding MyObject1}" />
        <DataGridTextColumn Header="MyObject2" Binding="{Binding MyObject2}" />
   </DataGrid.Columns>
</DataGrid>

在另一方面,我假定的ItemsSource 的DataGrid 元素的集合对象(或课程的类似的东西,)

In the other hand, I assume the ItemsSource of your DataGrid is a collection of Element objects (or something similar, of course)

public class Element
{
    public string Name { get; set; }
    public MyObject MyObject1 { get; set; }
    public MyObject MyObject2 { get; set; }
}
public class MyObject
{
    public string Name { get; set; }
    public bool IsEnabled { get; set; }
    public override string ToString()
    {
        return Name;
    }
}



最后,转换器:

Finally, the converter:

public class DataGridCellToBooleanConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        string propertyToAppend = parameter as string;
        var cell = value as DataGridCell;
        var column = cell.Column as DataGridTextColumn;
        Binding b = column.Binding as Binding;
        Binding b1 = new Binding(string.Join(".", b.Path.Path, propertyToAppend)) { Source = cell.DataContext };
        CheckBox dummy = new CheckBox();
        dummy.SetBinding(CheckBox.IsCheckedProperty, b1);
        return dummy.IsChecked;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}



棘手的部分是使用 ConverterParameter 为了打发你想在 DataTrigger 绑定属性的名称。

The tricky part is using the ConverterParameter in order to pass the name of the property you want to bind in the DataTrigger.

P.S。您可以使用反射,而不是哈克复选框假元素,但是这对我的作品。

P.S. You can use reflection instead of the hacky CheckBox dummy element, but this works for me.

希望这有助于

这篇关于根据价值变动细胞 - WPF的DataGrid结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆