如何将 DataGridTemplateColumn 绑定到列值而不是行值?

发布于 2024-09-30 11:54:11 字数 1285 浏览 5 评论 0原文

我有一个属性网格控件,它有许多单元格编辑器,可以使用 CellEditorTemplateSelector 自动应用。每个属性网格行都绑定到一个简单的 PropertyItemViewModel。

现在,我尝试重用所有这些单元格编辑器并将其呈现在 DataGrid 中,以便能够并排比较多个对象值。因此,我添加了一个 PropertiesRow 对象,其中包含 PropertyItemViewModel 列表(与上面的属性网格相同)。

为了呈现每个单元格,我有一个简单的数据模板,它使用与属性网格相同的模板选择器。

<DataTemplate x:Key="CellDataTemplate">
    <ContentControl
         Content="{Binding Mode=OneWay}"
         ContentTemplateSelector="{StaticResource CellEditorTemplateSelector}" />            
</DataTemplate>

但是,为了使其正常工作,模板需要一个 PropertyItemViewModel (而不是 PropertiesRow),因此我必须以某种方式通过从 PropertiesRow.PropertyItems[columnIndex] 获取正确的绑定来提供它。因此,当我通过代码添加列时,我尝试了如下操作:

void AddColumns()
{
    foreach (Property shownProperty in _ShownProperties)
    {
        _DataGrid.Columns.Add(new DataGridTemplateColumn()
        {
            Header = shownProperty.Name;
            Binding = new Binding("PropertyItems[" + index + "]");
            CellTemplate = (DataTemplate) FindResource("CellDataTemplate");
        });
    }
}

但是,DataGridTemplateColumn 没有 Binding 属性!因此,我尝试为每个列生成一个中间 DataTemplate,但这开始变得非常复杂,而且我觉得必须有一种更简单的方法来执行此操作。

有什么建议吗?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

╄→承喏 2024-10-07 11:54:11

我在使用上面的 XAML 时遇到了问题,但我让它工作了。必须设置 Path='' 否则编译器会不满意。

Content="{Binding Mode=OneWay, Path='',
                  RelativeSource={RelativeSource FindAncestor, AncestorType=DataGridCell, 
                                  AncestorLevel=1}, 
                  Converter={StaticResource CellToColumnValueConverter}}"

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}}"
不再见 2024-10-07 11:54:11

我找到了一种方法来做到这一点,根据 MVVM 标准,这种方法并不干净,因为它直接使用 DataGridCells,但在其他方面它工作得很好。

我按原样保留了单元格模板,只是没有将其绑定到 PropertiesRow 对象(该对象没有指示我们位于哪一列),而是使用相对源绑定到父 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>

然后添加了一个 CellToColumnValueConverter 它采用 DataGridCell 并使用列的索引将其转换为 PropertyItem:

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();
    }
}

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();
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文