wpf 中获取datagrid中的值

本文介绍如何使用C#代码批量设置DataGridView控件中指定行和列的单元格是否启用,包括隐藏特定单元格及获取模板控件内的子控件。

public static void SetDataGridCellIsEnabled(DataGrid datagrid, int rowIndex, int[] cellIndexArray, bool IsEnabled)
        {
            for (int index = 0; index < cellIndexArray.Length; index++)
            {
                DataGridCell currentCell = GetDataGridCell(datagrid, rowIndex, cellIndexArray[index]);
                if (currentCell != null)
                {
                    currentCell.IsEnabled = IsEnabled;

                    这行代码是隐藏单元格

 


--------------------------------------------------------------------------------


                    Button button1= currentCell.ChildrenOfType<Button>();

                     这行代码是得到模板控件里的子控件
                }
            }
        }

        public static DataGridCell GetDataGridCell(DataGrid datagrid, int rowIndex, int columnIndex)
        {
            try
            {
                DataGridRow rowContainer = GetDataGridRow(datagrid, rowIndex);
               
                if (rowContainer != null)
                {
                    DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(rowContainer);

                    这行代码是通过行得到单元格


--------------------------------------------------------------------------------

                    DataGridCell cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex);

                    这行代码是通过index得到具体的单元格

 

--------------------------------------------------------------------------------

                    if (cell == null)
                    {
                        datagrid.ScrollIntoView(rowContainer, datagrid.Columns[columnIndex]);
                        cell = (DataGridCell)presenter.ItemContainerGenerator.ContainerFromIndex(columnIndex);
                    }

                    return cell;
                }
            }
            catch
            {
                return null;
            }
            return new DataGridCell();
        }

        public static DataGridRow GetDataGridRow(DataGrid datagrid, int rowIndex)
        {
            DataGridRow row = (DataGridRow)datagrid.ItemContainerGenerator.ContainerFromIndex(rowIndex);

            这行代码的作用是得到datagrid的一行


--------------------------------------------------------------------------------


            if (row == null)
            {
                datagrid.UpdateLayout();
                //datagrid.ScrollIntoView(datagrid.Items[rowIndex]);
                row = (DataGridRow)datagrid.ItemContainerGenerator.ContainerFromIndex(rowIndex);
            }
            return row;
        }

        public static T GetVisualChild<T>(Visual parent) where T : Visual
        {
            T childContent = default(T);
            int numVisuals = VisualTreeHelper.GetChildrenCount(parent);
            for (int i = 0; i < numVisuals; i++)
            {
                Visual v = (Visual)VisualTreeHelper.GetChild(parent, i);
                childContent = v as T;
                if (childContent == null)
                {
                    childContent = GetVisualChild<T>(v);
                }
                if (childContent != null)
                {
                    break;
                }
            }
            return childContent;
        }

 

本文来自优快云博客,转载请标明出处:http://blog.youkuaiyun.com/xiaozhiboxiaozhibo/archive/2010/04/26/5529603.aspx

<think>我们正在讨论的是WPF中的DataGrid控件,用户想要了解如何获取DataGrid中的。根据之前的引用和对话历史,我们可以总结出以下几种常见的获取DataGrid的方法: 1. **获取选中行**:通过绑定SelectedItem或者处理选中事件来获取当前选中的数据。 2. **获取特定单元格的**:通过行索引和列索引或列名来获取特定单元格的。 3. **获取所有行的数据**:直接访问DataGrid的Items集合。 4. **获取可见行数据**:通过监听滚动事件和计算可视区域来获取当前可见的行。 5. **获取复选框勾选的行**:遍历DataGrid的Items,检查复选框列的状态来获取中的行。 此外,我们需要注意在MVVM模式下的做法,尽量避免在后台代码中直接操作控件,而是通过绑定和命令来实现。 下面我们将详细介绍这些方法。 ### 1. 获取选中行 在WPF中,DataGrid控件有一个SelectedItem属性,可以绑定到ViewModel中的属性,或者通过事件处理程序获取。 **XAML绑定示例**(MVVM模式): ```xml <DataGrid x:Name="dataGrid" SelectedItem="{Binding SelectedDataItem}" ... /> ``` 在ViewModel中,我们可以定义一个属性来接收选中的项: ```csharp private YourDataType _selectedDataItem; public YourDataType SelectedDataItem { get { return _selectedDataItem; } set { _selectedDataItem = value; OnPropertyChanged(nameof(SelectedDataItem)); } } ``` **通过事件获取**(非MVVM模式): 我们可以在SelectionChanged事件中获取: ```csharp private void dataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e) { var selectedItem = dataGrid.SelectedItem as YourDataType; // 处理selectedItem } ``` 另外,引用[2]中展示了通过鼠标双击事件来获取选中行,并传递给命令: ```xml <DataGrid.InputBindings> <MouseBinding Command="{Binding OpenWindowCommand}" CommandParameter="{Binding ElementName=NewPlanDataGrid, Path=SelectedItem}" Gesture="LeftDoubleClick" /> </DataGrid.InputBindings> ``` ### 2. 获取特定单元格的 有时我们需要获取特定行和列的单元格的。引用[5]展示了如何通过行索引和列索引来获取单元格的。 例如,我们想获取第i行第2列(索引从0开始)的单元格的: ```csharp // 假设第2列是DataGridTextColumn,其内容是一个TextBlock // 注意:当单元格是编辑状态时,可能是文本框,所以需要判断 var cellContent = dataGrid.Columns[2].GetCellContent(dataGrid.Items[i]); if (cellContent is TextBlock textBlock) { string cellValue = textBlock.Text; } ``` 但是,这种方法依赖于列的显示方式,如果列模板复杂,可能不是TextBlock。更通用的做法是直接访问数据项。 另一种方法是直接访问行的数据对象,然后通过属性名获取: ```csharp // 假设数据项类型为YourDataType var item = dataGrid.Items[i] as YourDataType; if (item != null) { string value = item.PropertyName; // 替换为实际的属性名 } ``` ### 3. 获取所有行的数据 DataGrid的Items属性就是所有行的数据集合。我们可以遍历Items: ```csharp foreach (var item in dataGrid.Items) { YourDataType dataItem = item as YourDataType; // 处理每一项 } ``` ### 4. 获取可见行数据 引用[1]提到,可以通过监听ScrollViewer的ScrollChanged事件来获取当前可见的行。在DataGrid内部有一个ScrollViewer,我们可以找到它并监听事件。 首先,我们需要获取DataGrid内部的ScrollViewer: ```csharp public static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject { for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++) { DependencyObject child = VisualTreeHelper.GetChildren(obj, i); if (child != null && child is T) return (T)child; else { T childOfChild = FindVisualChild<T>(child); if (childOfChild != null) return childOfChild; } } return null; } // 在加载完成后获取ScrollViewer ScrollViewer scrollViewer = FindVisualChild<ScrollViewer>(dataGrid); if (scrollViewer != null) { scrollViewer.ScrollChanged += ScrollViewer_ScrollChanged; } ``` 然后在事件处理程序中计算可见行: ```csharp private void ScrollViewer_ScrollChanged(object sender, ScrollChangedEventArgs e) { // 获取第一个可见行和最后一个可见行 // 方法1:使用ItemContainerGenerator var firstVisibleItem = dataGrid.ItemContainerGenerator.ContainerFromIndex(0) as DataGridRow; // 实际上,我们需要计算哪些行在视口内 // 方法2:使用VisualTreeHelper来遍历行,检查是否在视口内 List<object> visibleItems = new List<object>(); for (int i = 0; i < dataGrid.Items.Count; i++) { DataGridRow row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromIndex(i); if (row != null) { // 将行的边界矩形转换到ScrollViewer的坐标系 Rect rowBounds = new Rect(new Point(0, 0), row.RenderSize); row.TransformToAncestor(scrollViewer).TransformBounds(rowBounds); Rect scrollViewerBounds = new Rect(0, 0, scrollViewer.ViewportWidth, scrollViewer.ViewportHeight); if (scrollViewerBounds.IntersectsWith(rowBounds)) { visibleItems.Add(dataGrid.Items[i]); } } } // 现在visibleItems包含了当前可见的数据项 } ``` 注意:在MVVM中,我们可能需要使用附加行为来将可见行信息传递到ViewModel。 ### 5. 获取复选框勾选的行 引用[4]展示了如何遍历DataGrid的Items,检查每一行中复选框列的。 假设我们的数据项中有一个布尔属性IsSelected,并且该列绑定到这个属性。我们可以这样获取中的行: ```csharp List<YourDataType> selectedItems = new List<YourDataType>(); foreach (var item in dataGrid.Items) { YourDataType dataItem = item as YourDataType; if (dataItem != null && dataItem.IsSelected) { selectedItems.Add(dataItem); } } ``` 如果复选框列是使用DataGridCheckBoxColumn并且绑定到数据项的属性,那么直接访问该属性即可。 ### 注意事项 - 在MVVM模式下,尽量通过绑定来获取数据,避免直接访问控件。 - 当数据源是DataTable时,需要将item转换为DataRowView,如引用[4]中的做法。 - 如果列使用了模板(DataGridTemplateColumn),那么获取单元格内容可能需要根据具体的模板结构来查找子元素。 ### 总结 获取DataGrid有多种方法,具体取决于需要获取哪些数据(选中行、特定单元格、所有行、可见行、勾选的行)以及项目的架构(是否使用MVVM)。在MVVM中,我们倾向于使用绑定;而在后台代码中,我们可以直接访问DataGrid的Items和SelectedItem等属性。 --- **§§相关问题§§** 1. 在WPFDataGrid中,如何通过绑定获取选中行而不使用事件处理程序? 2. 如何实现DataGrid的多选并获取所有选中的行? 3. 在MVVM模式下,如何将DataGrid的滚动位置信息传递给ViewModel? 4. 如何获取DataGrid中特定列的单元格的,而不依赖于列索引? 5. 当DataGrid绑定到DataTable时,如何获取数据? </think>在 WPF获取 `DataGrid` 控件的方法主要有以下几种,根据不同的使用场景选择合适的方式: ### 一、获取选中行数据(推荐方式) **使用绑定获取当前选中行**(MVVM友好): ```xml <DataGrid x:Name="dataGrid" SelectedItem="{Binding SelectedDataItem}" ItemsSource="{Binding Items}"/> ``` 在 ViewModel 中: ```csharp private YourDataType _selectedDataItem; public YourDataType SelectedDataItem { get => _selectedDataItem; set => SetProperty(ref _selectedDataItem, value); } // 通过命令获取(引用[2]示例) <MouseBinding Command="{Binding OpenWindowCommand}" CommandParameter="{Binding ElementName=dataGrid, Path=SelectedItem}"/> ``` ### 二、获取特定单元格的 **后台代码获取**(根据行列索引): ```csharp // 获取第i行第2列的(引用[5]示例) var cellValue = (dataGrid.Columns[1].GetCellContent(dataGrid.Items[i]) as TextBlock)?.Text; ``` **通过数据对象获取**(更推荐): ```csharp var item = dataGrid.Items[i] as YourDataType; if(item != null) { string value = item.PropertyName; // 直接访问绑定属性 } ``` ### 三、获取所有行的数据 **遍历 Items 集合**: ```csharp foreach(var item in dataGrid.Items) { if(item is YourDataType dataItem) { // 访问dataItem的属性 } } ``` ### 四、获取带复选框的选中行(引用[4]) ```csharp var selectedItems = new List<YourDataType>(); foreach(var item in dataGrid.Items) { if(item is YourDataType dataItem && dataItem.IsSelected) { selectedItems.Add(dataItem); } } ``` ### 五、获取可见行数据(引用[1]) ```csharp // 在DataGrid加载完成后添加事件 private void DataGrid_Loaded(object sender, RoutedEventArgs e) { var scrollViewer = FindVisualChild<ScrollViewer>(dataGrid); scrollViewer.ScrollChanged += (s, args) => { var visibleItems = new List<object>(); for(int i = 0; i < dataGrid.Items.Count; i++) { var row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromIndex(i); if(row != null && row.IsVisible) { visibleItems.Add(dataGrid.Items[i]); } } }; } // 辅助方法:查找视觉子元素 private static T FindVisualChild<T>(DependencyObject obj) where T : DependencyObject { for(int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++) { var child = VisualTreeHelper.GetChild(obj, i); if(child is T result) return result; var childResult = FindVisualChild<T>(child); if(childResult != null) return childResult; } return null; } ``` ### 最佳实践建议 1. **优先使用MVVM绑定**:通过 `SelectedItem` 或完整数据集合操作,避免直接访问UI元素[^1][^2] 2. **避免直接访问单元格**:直接操作数据对象比访问UI元素更稳定 3. **性能考虑**:获取可见行时添加防抖处理,滚动事件可能频繁触发 4. **类型安全**:使用 `as` 转换而非强制转换,避免异常 --- **
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值