我需要的是是UserControl
能够列出与DataGrid
类似的列表项,这意味着它将包含行列表,每行将有一个{ {1}}但它有一些附加功能。
我尝试过两种不同的场景。
MainWindow.xaml
RowDetail
MainWindow.xaml.cs
<DataGrid ItemsSource="{Binding Employees}" >
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<DataGrid ItemsSource="{Binding Details}"/>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
Mainwindow.xaml.cs
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var detail1 = new EmployeeDetails() {ManagerID=11, ManagerName="11 Name" , ManagerMobile = "123456" };
var detail2 = new EmployeeDetails() { ManagerID = 12, ManagerName = "12 Name", ManagerMobile = "123456" };
var detail3 = new EmployeeDetails() { ManagerID = 13, ManagerName = "13 Name", ManagerMobile = "123456" };
var detail4 = new EmployeeDetails() { ManagerID = 11, ManagerName = "11 Name", ManagerMobile = "123456" };
var detail5 = new EmployeeDetails() { ManagerID = 12, ManagerName = "12 Name", ManagerMobile = "123456" };
var detail6 = new EmployeeDetails() { ManagerID = 13, ManagerName = "13 Name", ManagerMobile = "123456" };
var detail7 = new EmployeeDetails() { ManagerID = 11, ManagerName = "11 Name", ManagerMobile = "123456" };
var detail8 = new EmployeeDetails() { ManagerID = 12, ManagerName = "12 Name", ManagerMobile = "123456" };
var detail9 = new EmployeeDetails() { ManagerID = 13, ManagerName = "13 Name", ManagerMobile = "123456" };
var details1 = new List<EmployeeDetails>();
details1.Add(detail1);
details1.Add(detail2);
details1.Add(detail3);
var details2 = new List<EmployeeDetails>() {detail4, detail5, detail6};
var details3 = new List<EmployeeDetails>() { detail7, detail8, detail9 };
Employees = new List<Employee>();
Employees.Add(new Employee() { ID = 1, Name = "Name1" , Details = details1 });
Employees.Add(new Employee() { ID = 2, Name = "Name2", Details = details2 });
Employees.Add(new Employee() { ID = 3, Name = "Name3", Details = details3 });
this.DataContext = this;
}
public List<Employee> Employees { get; set; }
}
public class Employee
{
public int ID { get; set; }
public string Name { get; set; }
public List<EmployeeDetails> Details { get; set; }
}
public class EmployeeDetails
{
public int ManagerID { get; set; }
public string ManagerName { get; set; }
public string ManagerMobile { get; set; }
}
MainWindow.xaml.cs
<local:CustomDataGrid ItemsSource="{Binding Employees}">
<local:CustomDataGrid.RowDetails>
<DataGrid ItemsSource="{Binding Details}" />
</local:CustomDataGrid.RowDetails>
</local:CustomDataGrid>
CustomDataGrid.xaml
--------------Same as Scenario 1-----------------
CustomDataGrid.xaml.cs
<Grid>
<DataGrid x:Name="maingrid" AutoGenerateColumns="True" >
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<ContentControl Content="{Binding RowDetails, RelativeSource={RelativeSource AncestorType=UserControl}}"/>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
</Grid>
我预计场景2的工作方式与场景1类似,但奇怪的是它不起作用。
Scenarion 2的问题是,/// <summary>
/// Interaction logic for CustomDataGrid.xaml
/// </summary>
public partial class CustomDataGrid : UserControl
{
public CustomDataGrid()
{
InitializeComponent();
}
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register("ItemsSource"
, typeof(IList)
, typeof(CustomDataGrid)
, new PropertyMetadata(null, OnItemSourcechanged));
public IList ItemsSource
{
get { return (IList)GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public static readonly DependencyProperty RowDetailsProperty =
DependencyProperty.Register("RowDetails"
, typeof(object)
, typeof(CustomDataGrid));
private static void OnItemSourcechanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as CustomDataGrid).maingrid.ItemsSource = (IList)e.NewValue;
}
public object RowDetails
{
get { return GetValue(RowDetailsProperty); }
set { SetValue(RowDetailsProperty, value); }
}
}
中的RowDetail
在打开另一个DataGrid
项后关闭后才会打开。
关于如何使场景2与场景1类似地工作的任何想法。
答案 0 :(得分:1)
我会使用字符串来绑定details属性的名称......
<local:CustomDataGrid NewItemsSource="{Binding Employees}" CustomRowDetails="Details" />
使用自定义数据网格设置所选项目
<Grid>
<DataGrid x:Name="maingrid" AutoGenerateColumns="True" ItemsSource="{Binding NewItemsSource}" SelectedItem="{Binding SelItem}" >
<DataGrid.RowDetailsTemplate>
<DataTemplate>
<DataGrid ItemsSource="{Binding MyDetails, RelativeSource={RelativeSource AncestorType=UserControl}}"/>
</DataTemplate>
</DataGrid.RowDetailsTemplate>
</DataGrid>
</Grid>
通过反思
public partial class CustomDataGrid : UserControl, INotifyPropertyChanged
{
public CustomDataGrid()
{
InitializeComponent();
maingrid.DataContext = this;
}
public static readonly DependencyProperty NewItemsSourceProperty =
DependencyProperty.Register("NewItemsSource"
, typeof(IEnumerable)
, typeof(CustomDataGrid)
, new PropertyMetadata(null, OnItemSourcechanged));
public IEnumerable NewItemsSource
{
get { return (IEnumerable)GetValue(NewItemsSourceProperty); }
set
{
SetValue(NewItemsSourceProperty, value);
}
}
public static readonly DependencyProperty CustomRowDetailsProperty =
DependencyProperty.Register("CustomRowDetails"
, typeof(string)
, typeof(CustomDataGrid));
private static void OnItemSourcechanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
(d as CustomDataGrid).maingrid.ItemsSource = (IEnumerable)e.NewValue;
}
public string CustomRowDetails
{
get
{
return (string)GetValue(CustomRowDetailsProperty);
}
set {
SetValue(CustomRowDetailsProperty, value);
}
}
private object selItem;
public object SelItem
{
get { return selItem; }
set {
selItem = value;
MyDetails = (IEnumerable<object>)value.GetType().GetProperty(CustomRowDetails).GetValue(value, null); ;
OnPropertyChanged(() => SelItem);
OnPropertyChanged(() => MyDetails);
}
}
private IEnumerable<object> myDetails;
public IEnumerable<object> MyDetails
{
get { return myDetails; }
set { myDetails = value;
OnPropertyChanged(() => MyDetails);
}
}
#region INotifyPropertyChanged Members
/// <summary>
/// Raised when a property on this object has a new value.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged<T>(Expression<Func<T>> selectorExpression)
{
if (selectorExpression == null)
throw new ArgumentNullException("selectorExpression");
MemberExpression body = selectorExpression.Body as MemberExpression;
if (body == null)
throw new ArgumentException("The body must be a member expression");
OnPropertyChanged(body.Member.Name);
}
/// <summary>
/// Raises this object's PropertyChanged event.
/// </summary>
/// <param name="propertyName">The property that has a new value.</param>
protected virtual void OnPropertyChanged(string propertyName)
{
//this.VerifyPropertyName(propertyName);
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
}
#endregion // INotifyPropertyChanged Members
}