我有两个DataGrids。一个列出项目列表,另一个列出规范。
如果我在第一个网格中选择Monitor,则第二个网格应显示自己的规格。如果我选择CPU,它应该在另一个网格上显示其规格。
我正在寻找一个很好的解决方案来做到这一点。截至目前我正在计划创建一个具有字符串属性和DataTable的模型,因此我可以创建一个将动态表绑定到第二个网格。但我正在寻找像动态属性或更好的解决方案。
谢谢
答案 0 :(得分:1)
对于这种情况,我使用GenericRow和GenericTable类:
public class GenericRow : CustomTypeDescriptor, INotifyPropertyChanged
{
#region Private Fields
List<PropertyDescriptor> _property_list = new List<PropertyDescriptor>();
#endregion
#region INotifyPropertyChange Implementation
public event PropertyChangedEventHandler PropertyChanged = delegate { };
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
#endregion INotifyPropertyChange Implementation
#region Public Methods
public void SetPropertyValue<T>(string propertyName, T propertyValue)
{
var properties = this.GetProperties()
.Cast<PropertyDescriptor>()
.Where(prop => prop.Name.Equals(propertyName));
if (properties == null || properties.Count() != 1)
{
throw new Exception("The property doesn't exist.");
}
var property = properties.First();
property.SetValue(this, propertyValue);
OnPropertyChanged(propertyName);
}
public T GetPropertyValue<T>(string propertyName)
{
var properties = this.GetProperties()
.Cast<PropertyDescriptor>()
.Where(prop => prop.Name.Equals(propertyName));
if (properties == null || properties.Count() != 1)
{
throw new Exception("The property doesn't exist.");
}
var property = properties.First();
return (T)property.GetValue(this);
}
public void AddProperty<T, U>(string propertyName) where U : GenericRow
{
var customProperty =
new CustomPropertyDescriptor<T>(
propertyName,
typeof(U));
_property_list.Add(customProperty);
}
#endregion
#region Overriden Methods
public override PropertyDescriptorCollection GetProperties()
{
var properties = base.GetProperties();
return new PropertyDescriptorCollection(
properties.Cast<PropertyDescriptor>()
.Concat(_property_list).ToArray());
}
#endregion
}
和
public class GenericTable
{
private string tableName = "";
public string TableName
{
get { return tableName; }
set { tableName = value; }
}
private ObservableCollection<DataGridColumn> columnCollection;
public ObservableCollection<DataGridColumn> ColumnCollection
{
get { return columnCollection; }
private set { columnCollection = value; }
}
private ObservableCollection<GenericRow> genericRowCollection;
public ObservableCollection<GenericRow> GenericRowCollection
{
get { return genericRowCollection; }
set { genericRowCollection = value; }
}
public GenericTable(string tableName)
{
this.TableName = tableName;
ColumnCollection = new ObservableCollection<DataGridColumn>();
GenericRowCollection = new ObservableCollection<GenericRow>();
}
/// <summary>
/// ColumnName is also binding property name
/// </summary>
/// <param name="columnName"></param>
public void AddColumn(string columnName)
{
DataGridTextColumn column = new DataGridTextColumn();
column.Header = columnName;
column.Binding = new Binding(columnName);
ColumnCollection.Add(column);
}
public override string ToString()
{
return TableName;
}
}
您可以使用这两个类来创建动态行和列。使用GenericRow类,您可以生成具有所需属性名称的行,并且可以使用相同的属性名称作为探测器绑定的列。
对于XAML方面:
<DataGrid Name="dataGrid"
local:DataGridColumnsBehavior.BindableColumns="{Binding ColumnCollection}"
AutoGenerateColumns="False"
...>
最后是DataGridColumsBehaior:
public class DataGridColumnsBehavior
{
public static readonly DependencyProperty BindableColumnsProperty =
DependencyProperty.RegisterAttached("BindableColumns",
typeof(ObservableCollection<DataGridColumn>),
typeof(DataGridColumnsBehavior),
new UIPropertyMetadata(null, BindableColumnsPropertyChanged));
private static void BindableColumnsPropertyChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
DataGrid dataGrid = source as DataGrid;
ObservableCollection<DataGridColumn> columns = e.NewValue as ObservableCollection<DataGridColumn>;
dataGrid.Columns.Clear();
if (columns == null)
{
return;
}
foreach (DataGridColumn column in columns)
{
dataGrid.Columns.Add(column);
}
columns.CollectionChanged += (sender, e2) =>
{
NotifyCollectionChangedEventArgs ne = e2 as NotifyCollectionChangedEventArgs;
if (ne.Action == NotifyCollectionChangedAction.Reset)
{
dataGrid.Columns.Clear();
foreach (DataGridColumn column in ne.NewItems)
{
dataGrid.Columns.Add(column);
}
}
else if (ne.Action == NotifyCollectionChangedAction.Add)
{
foreach (DataGridColumn column in ne.NewItems)
{
dataGrid.Columns.Add(column);
}
}
else if (ne.Action == NotifyCollectionChangedAction.Move)
{
dataGrid.Columns.Move(ne.OldStartingIndex, ne.NewStartingIndex);
}
else if (ne.Action == NotifyCollectionChangedAction.Remove)
{
foreach (DataGridColumn column in ne.OldItems)
{
dataGrid.Columns.Remove(column);
}
}
else if (ne.Action == NotifyCollectionChangedAction.Replace)
{
dataGrid.Columns[ne.NewStartingIndex] = ne.NewItems[0] as DataGridColumn;
}
};
}
public static void SetBindableColumns(DependencyObject element, ObservableCollection<DataGridColumn> value)
{
element.SetValue(BindableColumnsProperty, value);
}
public static ObservableCollection<DataGridColumn> GetBindableColumns(DependencyObject element)
{
return (ObservableCollection<DataGridColumn>)element.GetValue(BindableColumnsProperty);
}
}
最后,您可以创建GenericRows并将它们添加到GenericTable中。它就像一个小视图模型。在XAML方面,不要忘记将rowscollection绑定为DataGrid的itemsource。