如何在代码中访问DataGridCell的数据对象?

7
基本上,我已经将数据网格绑定,使其类似于科目的时间表 - 每行代表一个学期的科目,该学期内的每个单元格代表一个科目。
现在,我正在尝试添加拖放功能,以便您可以将其他科目拖放到网格上,并更新底层数据结构。
我可以使用一些可视化树方法来查找用户正在将新科目拖放到的DataGridCell,但我不知道如何访问该单元格绑定的值(即科目),以便用新科目替换空/占位符值。是否有一种访问基础值的方法,还是应该重新构建创建此程序的方法?
一个示例的网格和要拖放到其上的科目的图像如下所示:

我已经更新了原始帖子。 - Migwell
你的意思是要将它从列表拖到网格中吗? - Freelancer
为什么你不在点击列表项时进行工作? - Freelancer
这不是很直观。我知道使用DataGrid的当前值等会更容易,但我宁愿不这样做。 - Migwell
好的,我喜欢你的想法。不知道解决方案。只能给你的想法点赞。 - Freelancer
显示剩余4条评论
1个回答

3

要获取DataGridCell的数据,您可以使用它的DataContext和Column属性。如何实现取决于行数据是什么,即您将哪些项目放入DataGrid的ItemsSource集合中。假设您的项目是数组:

// 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];

如果您的行数据更复杂,您需要编写相应的方法来将“列”属性和行数据项翻译为其在行数据项上的特定值。

编辑:

如果您将数据拖放到的单元格不是选定单元格,则一种选择是使用VisualTreeHelper获取所属于DataGridCellDataGridRow

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

接下来您就可以按照上述步骤进行操作。


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

行为提供了一种非常直观的方式来从C#代码扩展控件的功能,而不是XAML,并保持您的代码干净简单(如果您遵循MVVM,则不仅仅是好的)。 行为被设计为可重用且不绑定于特定的控件。

这里是一个很好的介绍

对于您的特殊情况,我只能给您一个想法:

编写一个 DropBehavior ,用于处理TextBlock控件(或您要在DataGridCells中放置的任何其他控件)的拖放。 基本思路是在您的控件的 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中,然后将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>

您可以在

System.Windows.Interactivity.dll

中找到Behavior<T>基类。

虽然我没有测试过,但我希望它能为您工作,并且您能理解这个概念...


我会看一下WPF Behaviours的东西,谢谢提供链接。但是对于你回答的第一部分,我无法使用你的任何一个解决方案。在第一个示例中,您使用DataGrid.SelectedCells [0]返回一个DataGridCellInfo,而我没有。请记住,我只有从拖放后鼠标位置得到的DataGridCell,我没有选择。我可以选择此单元格,然后执行此方法,但我宁愿不更改用户的选择。 - Migwell
在第二种方法中,您使用rowData [Column Index]。我可以获取列索引,因为我有该列(它是DataGridCell的属性),但我不知道单元格的当前行,以便获取正确的rowData结构。 - Migwell
@Miguel:我已经编辑了我的帖子。我强烈建议使用行为。它真的不那么复杂,而且在我看来,所有这些搜索父行和转换都既不好看也不高效。 - Marc

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接