[英]WPF Datagrid flatten collections of collection objects
I need your help. 我需要你的帮助。 I have a collection of objects which has collections inside and I need to display the values inside of them. 我有一个对象集合,里面有集合,我需要在其中显示值。
This is my collection Element. 这是我的收藏元素。 A List of them will later be bound to the Datagrid (ObjectBase is only an implementation of INotifyPropertyChanged) 它们的列表稍后将绑定到Datagrid(ObjectBase只是INotifyPropertyChanged的实现)
public class ElementContainer : ObjectBase
{
public Element ContainerElement { get; set; }
private ObservableCollection<State> _elementStates;
public ObservableCollection<State> ElementStates
{
get { return _elementStates; }
set { _elementStates = value; OnPropertyChanged(); }
}
}
My elements: 我的元素:
public class Element
{
public int Nbr { get; set; }
public string Name { get; set; }
}
public class State: ObjectBase
{
public string Name { get; set; }
private bool _value;
public bool Value
{
get { return _value; }
set { _value = value; OnPropertyChanged(); }
}
public string StateType { get; set; }
}
The "Value" property of the State object is what I need get updated if it changed. State对象的“ Value”属性是我需要更改的内容。
My ViewModel: 我的ViewModel:
public class MainViewModel : ObjectBase
{
private IList<ElementContainer> _enitites;
public IList<ElementContainer> Enitites
{
get { return _enitites; }
set { _enitites = value; OnPropertyChanged(); }
}
public MainViewModel()
{
Enitites = new ObservableCollection<ElementContainer>()
{
new ElementContainer() {
ContainerElement = new Element() {Nbr= 1, Name= "Test 1" },
ElementStates = new ObservableCollection<State>()
{
new State() { Name = "On", Value = true, StateType= "On" },
new State() { Name = "Open", Value = false, StateType= "Open" }
}
},
new ElementContainer() {
ContainerElement = new Element() {Nbr= 2, Name= "Test 2" },
ElementStates = new ObservableCollection<State>()
{
new State() { Name = "On", Value = false, StateType= "On" },
new State() { Name = "Open", Value = true, StateType= "Open" }
}
}
};
}
}
Now the Datagrid should have following columns: 现在,Datagrid应该具有以下列:
Nbr, Name, On, Open Nbr,名称,开启,打开
The CellValue of the "On" and "Open" columns should be the value property of the State. “打开”和“打开”列的CellValue应该是State的value属性。
Any ideas? 有任何想法吗?
Edit: 编辑:
What I also tried is to create an AttachedProperty for creating the columns: 我还尝试了创建用于创建列的AttachedProperty:
public class ElementStatesGridExtensions
{
public static ObservableCollection<ColumnConfig> GetColumnConfigs(DependencyObject obj)
{
return (ObservableCollection<ColumnConfig>)obj.GetValue(ColumnConfigsProperty);
}
public static void SetColumnConfigs(DependencyObject obj, ObservableCollection<ColumnConfig> value)
{
obj.SetValue(ColumnConfigsProperty, value);
}
public static readonly DependencyProperty ColumnConfigsProperty =
DependencyProperty.RegisterAttached("ColumnConfigs", typeof(ObservableCollection<ColumnConfig>), typeof(ElementStatesGridExtensions), new PropertyMetadata(new PropertyChangedCallback(OnColumnsChanged)));
static DeviceStateConverter converter = new DeviceStateConverter();
static FrameworkElementFactory CreateFrameWorkFactoryWithBinding(ColumnConfig config)
{
var fwf = new FrameworkElementFactory(typeof(TextBlock));
if (config != null && config.ColumnType != null)
{
if (config.ColumnType.Equals("State"))
{
fwf.SetBinding(TextBlock.TextProperty, new Binding("ElementStates")
{
ConverterParameter = config.ColumnName,
Converter = converter,
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
Mode = BindingMode.OneWay
});
}
}
return fwf;
}
static void OnColumnsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var dataGrid = d as DataGrid;
dataGrid.Columns.Clear();
dataGrid.Columns.Add(new DataGridTextColumn() { Header = "Nbr", Binding = new Binding("ContainerElement.Nbr") });
dataGrid.Columns.Add(new DataGridTextColumn() { Header = "Name", Binding = new Binding("ContainerElement.Name") });
foreach (var columnConfig in GetColumnConfigs(d))
{
dataGrid.Columns.Add(new DataGridTemplateColumn()
{
Header = columnConfig.ColumnHeader,
CellTemplate = new DataTemplate()
{
VisualTree = CreateFrameWorkFactoryWithBinding(columnConfig)
}
});
}
}
}
public class DeviceStateConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is ObservableCollection<stof.State> deviceStates && parameter != null)
{
var deviceState = deviceStates.FirstOrDefault(s => s.StateType?.ToUpper() == parameter.ToString().ToUpper());
if (deviceState != null)
return deviceState.Value;
}
return false;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Then I attached this property to the datagrid. 然后,我将此属性附加到datagrid。 And added this ... 并添加了这个...
public void RefeshStates(object sender, EventArgs e)
{
OnPropertyChanged("ElementStates");
}
to the ElementContainer class. 到ElementContainer类。
Then in the ViewModel I iterate through all entities and register the PropertyChanged event of every state to the ElementContainer. 然后,在ViewModel中,我遍历所有实体,并将每个状态的PropertyChanged事件注册到ElementContainer。 So now if the state value changes, the Container gets notified and the Collection will refresh. 因此,现在如果状态值更改,则将通知Container,并且Collection将刷新。 That's not a good solution. 那不是一个好的解决方案。 Also the states of all other elements will be updated. 同样,所有其他元素的状态也将被更新。
foreach (ElementContainer container in Enitites)
{
foreach (State s in container.ElementStates)
{
s.PropertyChanged += container.RefeshStates;
}
}
Is ElementStates
length always 2? ElementStates
长度是否总是2? if yes than tere are two options: 如果是,则有两个选择:
State
values into your ElementContainer
class as Properties. 选项1:您可以将两个State
值作为Properties包括在ElementContainer
类中。 var q = Enitites.Select(e=>e.Nbr, e.Name, e.ElementStates.Where(es=>es.Name="On").First().Value, e.ElementStates.Where(es=>es.Name="Open").First().Value);
选项2:您可以调用类似这样的var q = Enitites.Select(e=>e.Nbr, e.Name, e.ElementStates.Where(es=>es.Name="On").First().Value, e.ElementStates.Where(es=>es.Name="Open").First().Value);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.