原文: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= "設備類型"
"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= "設備總數"
"100" />
<DataGridTextColumn Binding= "{Binding Count_no}" FontSize= "25" FontWeight= "Bold"
"Red" Header= "未使用數量" Width= "115" />
<DataGridTextColumn Binding= "{Binding Count_yes}" FontSize= "22" Foreground= "Green"
"使用中數量" Width= "115" />
</DataGrid.Columns>
<DataGrid.RowDetailsTemplate >
<DataTemplate >
<DataGrid Name= "dataGrid2" Width= "1070" SelectedValuePath = "dept_code" IsReadOnly= "True"
"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= "廠房代碼"
"85" />
<DataGridTextColumn Binding= "{Binding floor}" FontSize= "22" Header= "樓層"
"70" />
<DataGridTextColumn Binding= "{Binding dept_name}" FontSize= "22" Header= "部門名稱"
"430" />
<DataGridTextColumn Binding= "{Binding count_all}" FontSize= "22" Header= "設備總數"
"100" />
<DataGridTextColumn Binding= "{Binding count_no}" FontSize= "25" FontWeight= "Bold"
"Red" Header= "未使用數量" Width= "115"
<DataGridTextColumn Binding= "{Binding count_yes}" FontSize= "22" Foreground= "Green"
"使用中數量" 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
{ /// <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
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
}
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
}
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
{
//下面的两行代码很关键
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
//详细信息
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 ; }
}
} |
代码虽然很多,但是看下来不觉得繁琐。在这里还要感叹一下,微软的东西,尤其是控件这种东西封装的太死了,你用第三方的控件其实还不如自己写,能明白很多东西。欢迎大家批评指正。