我需要你的帮助。我有一个对象集合,里面有集合,我需要显示它们内部的值。
这是我的收藏元素。它们的列表稍后将绑定到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(); }
}
}
我的元素:
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; }
}
State对象的“Value”属性是我需要更新的内容,如果它发生了变化。
我的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" }
}
}
};
}
}
现在,Datagrid应该包含以下列:
Nbr,姓名,开启,打开
“On”和“Open”列的CellValue应该是State的value属性。
有什么想法吗?
编辑:
我还尝试创建一个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();
}
}
然后我将此属性附加到datagrid。 并添加了这个......
public void RefeshStates(object sender, EventArgs e)
{
OnPropertyChanged("ElementStates");
}
到ElementContainer类。
然后在ViewModel中迭代所有实体并将每个状态的PropertyChanged事件注册到ElementContainer。 所以现在,如果状态值发生变化,则会通知Container并且Collection将刷新。这不是一个好的解决方案。此外,所有其他元素的状态都将更新。
foreach (ElementContainer container in Enitites)
{
foreach (State s in container.ElementStates)
{
s.PropertyChanged += container.RefeshStates;
}
}
答案 0 :(得分:0)
ElementStates
长度总是2吗?如果是,则有两个选项:
State
两个值都包含在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);