WPF 实现主从的datagrid以及操作rowdetailtemplate 的方法

本文介绍了如何在WPF中实现主从Datagrid,并详细讲解了如何操作RowDetailTemplate,包括主从表数据的折叠、隐藏及从表数据的获取和操作。通过实例代码展示了具体实现过程,同时作者对微软控件的封装特性进行了讨论。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文: WPF 实现主从的datagrid以及操作rowdetailtemplate 的方法

WPF 实现主从的datagrid以及操作rowdetailtemplate 的方法

       最近在做一个项目,其中要用到主从表数据的折叠和隐藏,并且对从表中的数据能够获取和操作,虽然搞了好久,但最终被我推敲出来了,写出来分享一下,让朋友少走弯路,废话不说了,先上效果图:

下面是代码:

 
前台   
<DataGrid ItemsSource= "{Binding}" Name= "dataGrid1" MouseUp= "dataGrid1_MouseUp" ...>   
<DataGrid.Columns>   
                    <DataGridTemplateColumn Width= "Auto" >   
                        <DataGridTemplateColumn.CellTemplate>   
                            <DataTemplate>   
                                <Expander Expanded= "Expander_Expanded" Collapsed= "Expander_Collapsed" />   
                            </DataTemplate>   
                        </DataGridTemplateColumn.CellTemplate>   
                    </DataGridTemplateColumn>   
                    <DataGridTextColumn Binding= "{Binding Facility_type}" FontSize= "22" Header= "設備類型"   Width= "120" />   
                    <DataGridTextColumn  FontSize= "22" Header= "廠房代碼" Width= "85" />   
                    <DataGridTextColumn  FontSize= "22"  Header= "樓層" Width= "70" />   
                    <DataGridTextColumn  FontSize= "22"   Header= "部門名稱" Width= "430" />   
                    <DataGridTextColumn Binding= "{Binding Count_all}" FontSize= "22"    Header= "設備總數"  Width= "100" />   
                    <DataGridTextColumn Binding= "{Binding Count_no}" FontSize= "25"  FontWeight= "Bold"   Foreground= "Red" Header= "未使用數量"  Width= "115" />   
                    <DataGridTextColumn Binding= "{Binding Count_yes}" FontSize= "22"  Foreground= "Green"  Header= "使用中數量"  Width= "115" />   
         
                </DataGrid.Columns>   
                <DataGrid.RowDetailsTemplate >   
                    <DataTemplate  >   
         
                        <DataGrid Name= "dataGrid2"  Width= "1070"  SelectedValuePath = "dept_code" IsReadOnly= "True"  HeadersVisibility= "None" HorizontalGridLinesBrush= "#FFE0E2DF" VerticalGridLinesBrush= "#FFE0E2DF"
                                  ItemsSource= "{Binding Details}" CanUserAddRows= "False" SelectionUnit= "FullRow"  AutoGenerateColumns= "False"  MouseUp= "dataGrid2_MouseUp" >   
                            <DataGrid.Columns>   
                                <DataGridTextColumn   Header= ""   Width= "150" />   
                                <DataGridTextColumn Binding= "{Binding building_code}" FontSize= "22" Header= "廠房代碼" Width= "85" />   
                                <DataGridTextColumn Binding= "{Binding floor}" FontSize= "22"  Header= "樓層" Width= "70" />   
                                <DataGridTextColumn Binding= "{Binding dept_name}" FontSize= "22"   Header= "部門名稱" Width= "430" />   
                                <DataGridTextColumn Binding= "{Binding count_all}" FontSize= "22"    Header= "設備總數"  Width= "100" />   
                                <DataGridTextColumn Binding= "{Binding count_no}"  FontSize= "25"  FontWeight= "Bold"  Foreground= "Red"  Header= "未使用數量"  Width= "115" />   
                                <DataGridTextColumn Binding= "{Binding count_yes}" FontSize= "22"  Foreground= "Green"  Header= "使用中數量"  Width= "115" />   
                            </DataGrid.Columns>   
                     </DataTemplate>   
                </DataGrid.RowDetailsTemplate>   
...   
</DataGrid>

下面是后台:

 
using System;    
using System.Data;    
using System.Windows;    
using System.Windows.Input;    
using System.Windows.Media;    
using System.Windows.Controls;    
using System.Collections.ObjectModel;    
using System.Windows.Threading;    
namespace Getac.DSP    
{    
    /// <summary>    
    /// HumanWork.xaml 的交互逻辑    
    /// </summary>    
    public partial class FacilitySum:Window    
    {    
        public  string Company_code;    
       // public string Select_item;    
        public ObservableCollection<Facility> Items { get ; set ; }    
        private delegate void ThreadDelegate(); //申明一个专用来调用更改线程函数的委托    
     public DispatcherTimer ShowTimer;    
        public FacilitySum(string company_code)    
        {    
            this .Company_code = company_code;    
            InitializeComponent();    
            this .WindowState = WindowState.Maximized;    
          }    
           
        private void Window_Loaded(object sender, RoutedEventArgs e)    
        {     
           //datagrid数据的加载    
            Items = new ObservableCollection<Facility>();    
            DataSet dsFacility = new BLL.DSP_FACILITY_USE().GetFacility_status_Sum(Company_code);    
            DataSet dsFacilityDetail = new BLL.DSP_FACILITY_USE().GetFacility_UseStatus(Company_code);    
            int count = dsFacility.Tables[ 0 ].Rows.Count;    
            for ( int i = 0 ; i < count; i++)    
            {    
                Items.Add( new Facility(Company_code, i, dsFacility, dsFacilityDetail));    
            }    
            dataGrid1.Items.Clear();    
            dataGrid1.ItemsSource  = Items;    
            dataGrid1.Items.Refresh();    
            dataGrid1.SelectedValuePath = "facility_type" ;    
           }    
           
        //展开,收缩子表的方法     
        private void Expander_Expanded(object sender, RoutedEventArgs e)    
        {    
            DataGridRow row = FindVisualParent<DataGridRow>(sender as Expander);    
            row.DetailsVisibility = System.Windows.Visibility.Visible;    
        }    
                    
        private void Expander_Collapsed(object sender, RoutedEventArgs e)    
        {    
            DataGridRow row = FindVisualParent<DataGridRow>(sender as Expander);    
            row.DetailsVisibility = System.Windows.Visibility.Collapsed;    
        }    
        public T FindVisualParent<T>(DependencyObject child) where T : DependencyObject    
        {    
            DependencyObject parentObject = VisualTreeHelper.GetParent(child);    
            if (parentObject == null ) return null ;    
            T parent = parentObject as T;    
            if (parent != null )    
                return parent;    
            else
                return FindVisualParent<T>(parentObject);    
        }    
         //下面的方法曾让我教头烂额,感叹微软的控件封装的太牛逼了,处理起来有点变态    
        /// <summary>    
        /// 找到行明细中嵌套的控件名称    
        /// </summary>    
        /// <typeparam name="T"></typeparam>    
        /// <param name="parent"></param>    
        /// <param name="name"></param>    
        /// <returns></returns>    
        public T FindVisualChildByName<T>(DependencyObject parent, string name) where T : DependencyObject    
         {    
             if (parent != null )    
             {    
                 for ( int i= 0 ;i<VisualTreeHelper.GetChildrenCount(parent);i++)    
                 {    
                     var child = VisualTreeHelper.GetChild(parent, i) as DependencyObject;    
                     string controlName=child.GetValue(Control.NameProperty) as string;    
                     if (controlName==name)    
                     {    
                         return child as T;    
                     }    
                     else
                     {    
                         T result=FindVisualChildByName<T>(child,name);    
                         if (result!= null )    
                             return result;    
                     }    
                 }    
             }    
             return null ;    
         }    
           
         //父表的事件处理驱动    
        private void dataGrid1_MouseUp(object sender, MouseButtonEventArgs e)    
        {    
            if (dataGrid1.CurrentCell.Column != null && dataGrid1.CurrentCell.Column.Header!= null )    
            {    
                string facility_type = (dataGrid1.Columns[ 1 ].GetCellContent(dataGrid1.CurrentCell.Item) as TextBlock).Text;    
                string head = dataGrid1.CurrentCell.Column.Header.ToString();    
                  //这边可以根据实际写自己的一些方法    
             }    
        }    
           
      //字表,也就是rowdetailtemplate中的datagrid 的事件处理方法,其中有调用上面的约束泛型类型的方法。    
        private void dataGrid2_MouseUp(object sender, MouseButtonEventArgs e)    
        {    
             //下面的两行代码很关键    
        DataGridRow dgr = (DataGridRow)dataGrid1.ItemContainerGenerator.ContainerFromIndex( this .dataGrid1.SelectedIndex);    
            DataGrid dg= FindVisualChildByName<DataGrid>(dgr, "dataGrid2" ) as DataGrid;    
             //获取鼠标点击的行每一单元格的值   
            string facility_type = (dataGrid1.Columns[ 1 ].GetCellContent(dataGrid1.CurrentCell.Item) as TextBlock).Text;    
            string building_code = (dg.Columns[ 1 ].GetCellContent(dg.CurrentCell.Item) as TextBlock).Text;    
            string floor = (dg.Columns[ 2 ].GetCellContent(dg.CurrentCell.Item) as TextBlock).Text;    
            string dept_code =dg.SelectedValue.ToString();    
            string head = dg.CurrentCell.Column.Header.ToString();    
            //获得一些信息后你可以自己写方法实现需要的功能    
        }    
    }    
    // 定义集合类用于存放栏位值    
    public class Facility    
    {    
        //static string FACILITY_TYPE;    
        public string Facility_type{ get ; set ; }    
        public string Building_code { get ; set ; }    
        public string Floor { get ; set ; }    
        public string Dept_code { get ; set ; }    
        public string Count_all { get ; set ; }    
        public string Count_no { get ; set ; }    
        public string Count_yes { get ; set ; }    
        public ObservableCollection<Facility_Detail> Details { get ; set ; }    
        public Facility(string company_code, int row_index,DataSet dsfacilitySum ,DataSet dsFacilityDetail)    
        {    
           
            Facility_type = dsfacilitySum.Tables[ 0 ].Rows[row_index][ "facility_type" ].ToString();    
            Count_all = dsfacilitySum.Tables[ 0 ].Rows[row_index][ "count_all" ].ToString();    
            Count_no = dsfacilitySum.Tables[ 0 ].Rows[row_index][ "count_no" ].ToString();    
            Count_yes = dsfacilitySum.Tables[ 0 ].Rows[row_index][ "count_yes" ].ToString();    
            Details = new ObservableCollection<Facility_Detail>();    
            //详细信息    
        System.Data.DataTable dtDetail = new System.Data.DataTable();    
            DataRow[] rowDetail = dsFacilityDetail.Tables[ 0 ].Select( "facility_type='" + Facility_type + "'" );    
            dtDetail = dsFacilityDetail.Tables[ 0 ].Clone();    
             foreach (DataRow dr in rowDetail)    
             {    
                 Details.Add( new Facility_Detail()    
                 {    
                     facility_type = Facility_type,    
                     building_code = dr[ "building_code" ].ToString(),    
                     floor = dr[ "floor" ].ToString(),    
                     dept_code = dr[ "dept_code" ].ToString(),    
                     dept_name = dr[ "dept_name" ].ToString(),    
                     count_all = dr[ "count_all" ].ToString(),    
                     count_no = dr[ "count_no" ].ToString(),    
                     count_yes = dr[ "count_yes" ].ToString()    
                 });    
             }    
        }    
    }    
    public class Facility_Detail    
    {   //定义属性 
        public string facility_type { get ; set ; }    
        public string building_code { get ; set ; }    
        public string floor { get ; set ; }    
        public string dept_code { get ; set ; }    
        public string dept_name { get ; set ; }    
        public string count_all { get ; set ; }    
        public string count_no { get ; set ; }    
        public string count_yes { get ; set ; }    
    }    
}

代码虽然很多,但是看下来不觉得繁琐。在这里还要感叹一下,微软的东西,尤其是控件这种东西封装的太死了,你用第三方的控件其实还不如自己写,能明白很多东西。欢迎大家批评指正。

posted on 2019-04-24 10:10 NET未来之路 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/lonelyxmas/p/10760755.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值