2017-08-22 8 views
0

私はあなたの助けが必要です。私は内部にコレクションを持っているオブジェクトのコレクションを持っており、それらの内部に値を表示する必要があります。WPF Datagridコレクションオブジェクトのフラットコレクション

これは私のコレクション要素です。 Stateオブジェクトの「値」プロパティは、私は必要なものである

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; } 
} 

:それらのリストは後で

public class ElementContainer : ObjectBase 
{ 
    public Element ContainerElement { get; set; } 

    private ObservableCollection<State> _elementStates; 

    public ObservableCollection<State> ElementStates 
    { 
     get { return _elementStates; } 
     set { _elementStates = value; OnPropertyChanged(); } 
    } 
} 

マイ要素(オブジェクトベースがINotifyPropertyChangedの唯一の実装である)データグリッドにバインドされます変更された場合は更新されます。

私の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" } 
             } 
            } 

     }; 
    } 
} 

今、データグリッドには、次ているはずの列:

NBR、名前、オン、オープン

"オン" と "オープン" の列のCellValueべき国家の価値財産であること。

アイデア?

編集:

私は何もしようとしたが、列を作成するための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(); 
    } 
} 

それから私は、データグリッドにこのプロパティを添付。 そして、この追加... ElementContainerクラスへ

public void RefeshStates(object sender, EventArgs e) 
    { 
     OnPropertyChanged("ElementStates"); 
    } 

次にViewModelですべてのエンティティを反復処理し、すべての状態のPropertyChangedイベントをElementContainerに登録します。 これで、状態値が変更されると、コンテナに通知され、コレクションが更新されます。それは良い解決策ではありません。他のすべての要素の状態も更新されます。

foreach (ElementContainer container in Enitites) 
     { 

      foreach (State s in container.ElementStates) 
      { 
       s.PropertyChanged += container.RefeshStates; 
      } 
     } 

答えて

0

ElementStatesは常に2ですか?

  1. オプション1:はいテレよりも二つのオプションしている場合は、プロパティとしてあなたElementContainerクラスに両方State値を含めることができます。
  2. オプション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);
+0

こんにちはDimos.Thankあなたのような何かを呼び出すことができます。要素の種類によって状態の数は異なりません。ユーザは後で要素タイプと彼が表示したいと思う状態を選択することができる。しかし、彼は1つの要素タイプしか選択できません。したがって、グリッド内のすべての要素は同じ型です。 – reiniX86

+0

ElementStatesリストに「On」と「Open」の状態が常にありますか?はいの場合、2番目のオプションは機能します –

+0

残念ながら、いいえ。ユーザーが見たい状態の名前はcolumnConfigsにあります。設定ダイアログを介して、ユーザはf.e.要素タイプ "TV"と状態 "IsOn"と "IsInputHDMI1"を選択するか、要素タイプ "Door"と状態 "IsOpen"を選択できます – reiniX86