【问题标题】:How can I access the data object of a DataGridCell in code?如何在代码中访问 DataGridCell 的数据对象?
【发布时间】:2013-02-27 23:43:13
【问题描述】:

基本上,我已经绑定了数据网格,使其类似于科目时间表 - 每行代表一个学期的科目,该学期中的每个单元格代表一个科目。

我现在正在尝试添加拖放功能,以便您可以将其他主题拖到网格上,这将更新底层数据结构。

我可以使用一些可视化树方法来查找用户将新主题拖动到的 DataGridCell,但我不知道如何访问单元格绑定到它的值(主题)以替换新主题的空白/占位符值。有没有办法访问底层价值,或者我应该重新构建创建这个程序的整个方法?

【问题讨论】:

  • 可以粘贴网格结构吗?
  • 物理GridView还是底层结构?
  • 只是列和示例数据
  • 我已经更新了原帖
  • 表示要将其从列表拖到网格?

标签: c# wpf c#-4.0 data-binding datagrid


【解决方案1】:

要获取 DataGridCell 的数据,您可以使用它的 DataContext 和 Column 属性。如何做到这一点完全取决于您的行数据是什么,即您在 DataGrid 的 ItemsSource 集合中放入了哪些项目。假设您的项目是 object[] 数组:

// Assuming this is an array of objects, object[],this gets you the 
// row data as you have them in the DataGrid's ItemsSource collection
var rowData = (object[]) DataGrid.SelectedCells[0].Item;
//  This gets you the single cell object
var celldata = rowData[DataGrid.SelectedCells[0].Column.DisplayIndex];

如果您的行数据更复杂,您需要编写一个相应的方法,将Column 属性和行数据项转换为行数据项上的特定值。


编辑:

如果您将数据放入的单元格不是选定的单元格,一种选择是使用VisualTreeHelper 获取DataGridCell 所属的DataGridRow

var parent = VisualTreeHelper.GetParent(gridCell);
while(parent != null && parent.GetType() != typeof(DataGridRow))
{
    parent = VisualTreeHelper.GetParent(parent);
}
var dataRow = parent;

那么你就有了行并且可以像上面那样继续。


此外,关于您是否应该重新考虑该方法的问题,我建议您使用自定义 WPF 行为

行为提供了一种非常直接的方式来从 C# 代码而不是 XAML 扩展控件的功能,同时保持代码隐藏清晰和简单(如果您遵循 MVVM,这不仅很好)。行为的设计方式使其可重复使用且不受您特定控件的约束。

Here's a good introduction

对于你的特殊情况,我只能告诉你该怎么做:

为您的 TextBlock 控件(或您想要在 DataGridCells 中处理拖放的任何控件)编写一个 DropBehavior。基本思想是在您的 OnAttached() 方法中为单元格的事件注册相应的操作控制。

public class DropBehavior : Behavior<TextBlock>
{
    protected override void OnAttached()
    {
        AssociatedObject.MouseUp += AssociatedObject_MouseUp;
    }

    private void AssociatedObject_MouseUp(object sender, MouseButtonEventArgs e)
    {
        // Handle what happens on mouse up

        // Check requirements, has data been dragged, etc.
        // Get underlying data, now simply as the DataContext of the AssociatedObject
        var cellData = AssociatedObject.DataContext;

    }
}

请注意,从行数据和Column 属性解析单个单元格的数据已过时。

然后,您使用 DataGrid 的 CellStyleContentTemplate 将此行为附加到 TextBlocks,然后将其放入单元格中:

<DataGrid>
    <DataGrid.CellStyle>
        <Style TargetType="DataGridCell">
            <Setter Property="ContentTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <TextBlock Text="{Binding}">
                            <i:Interaction.Behaviors>
                                <yourns:DropBehavior/>
                            </i:Interaction.Behaviors>
                        </TextBlock>
                    </DataTemplate>
                </Setter.Value>

            </Setter>
        </Style>
    </DataGrid.CellStyle>
</DataGrid>

您可以在

中找到Behavior&lt;T&gt; 基类

System.Windows.Interactivity.dll

我没有测试过它,但我希望它对你有用并且你明白了......

【讨论】:

  • 我会看看 WPF 行为的事情,谢谢你的链接。但是,对于您答案的第一部分,我无法执行您的任何一个解决方案。在第一个示例中,您使用 DataGrid.SelectedCells[0],它返回一个我没有的 DataGridCellInfo。请记住,我只有拖放后从鼠标位置获得的 DataGridCell,我没有选择。我可以选择此单元格,然后执行此方法,但我宁愿不必更改用户的选择。
  • 在第二种方法中,您使用 rowData[Column Index]。我可以得到列索引,因为我有列(它是 DataGridCell 的属性),但我不知道单元格的当前行以便获得正确的 rowData 结构。
  • @Miguel:我修改了我的帖子。我肯定会推荐使用行为。这真的没有那么复杂,恕我直言,所有这些搜索父行和四处转换既不是好的风格也不是有效的。
猜你喜欢
  • 1970-01-01
  • 2012-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-13
  • 1970-01-01
  • 2017-01-20
相关资源
最近更新 更多