2016-12-30 139 views
-2

我想將DataGrid綁定到嵌套屬性的集合。 我試過
WPF: Bound datagrid does not update items properties 的解決方案,但目前還沒有運氣。WPF將Datagrid綁定到具有嵌套屬性的ObservableCollection

我所得到的是一個空的DataGrid和控制檯輸出這樣的:

System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=AGNR.Key; DataItem=null; target element is 'DataGridTextColumn' (HashCode=38805039); target property is 'Header' (type 'Object')

而且輸出tcc_CollectionChanged(但不是PropertyChangedHandler):

30.12.2016 11:11:22, Collection changed

我用的是現代的UI(firstfloor)框架。這裏是我的窗口代碼:

public partial class Home : UserControl 
{ 

    private ObservableTable<TableClass> tcc; 

    public Home() 
    { 
     InitializeComponent(); 
    } 

    private void UserControl_Loaded(object sender, RoutedEventArgs e) 
    { 
     TableClass tc; 
     List<TableClass> tcl = new List<TableClass>(); 

     tcc = new ObservableTable<TableClass>(); 

     tcc.CollectionChanged += tcc_CollectionChanged; 
     tcc.ItemPropertyChanged += PropertyChangedHandler; 

     for (int i = 0; i < 10; i++) 
     { 
      tc = new TableClass(); 

      tc.AGNR.Name = "AGNr"; 
      tc.AGNR.Value = i.ToString(); 

      tc.MNR.Name = "MNr"; 
      tc.MNR.Value = i.ToString() + " M"; 

      tc.MST.Name = "MSt"; 
      tc.MST.Value = i % 2 == 0 ? "production" : "stopped"; 

      tcc.Add(tc); 
     } 

    } 

    static void PropertyChangedHandler(object sender, PropertyChangedEventArgs e) 
    { 
     Console.WriteLine(DateTime.Now.ToString() + ", Property changed"); 
     return; 
    } 

    static void tcc_CollectionChanged(object sender, EventArgs e) 
    { 
     Console.WriteLine(DateTime.Now.ToString() + ", Collection changed"); 
     return; 
    } 
} 

通訊XAML:

<UserControl x:Class="MuiWpfTestApp.Pages.Home" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     mc:Ignorable="d" 
     d:DesignHeight="300" d:DesignWidth="300" 
     Loaded="UserControl_Loaded"> 
<Grid Style="{StaticResource ContentRoot}"> 
    <ScrollViewer> 
     <DataGrid x:Name="tcgrid" ItemsSource="{Binding tcc, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Height="250" Width="250"> 
      <DataGridTextColumn Binding="{Binding AGNR.Value, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" 
           Header="{Binding AGNR.Key, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/> 
      <DataGridTextColumn Binding="{Binding MNR.Value, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" 
           Header="{Binding MNR.Key, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/> 
      <DataGridTextColumn Binding="{Binding MST.Value, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" 
           Header="{Binding MST.Key, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/> 
     </DataGrid> 
    </ScrollViewer> 
</Grid> 

INotifyPropertyChanged的是TableClass實現:

class TableClass : INotifyPropertyChanged 
{ 
    private KeyValueClass _mnr; 
    private KeyValueClass _agnr; 
    private KeyValueClass _mst; 

    public KeyValueClass MNR 
    { 
     get 
     { 
      return _mnr; 
     } 
     set 
     { 
      _mnr = value; 
      NotifyPropertyChanged("MNR"); 
     } 
    } 
    public KeyValueClass AGNR 
    { 
     get 
     { 
      return _agnr; 
     } 
     set 
     { 
      _agnr = value; 
      NotifyPropertyChanged("AGNR"); 
     } 
    } 
    public KeyValueClass MST 
    { 
     get 
     { 
      return _mst; 
     } 
     set 
     { 
      _mst = value; 
      NotifyPropertyChanged("MST"); 
     } 
    } 

    public TableClass() 
    { 
     MNR = new KeyValueClass(); 
     AGNR = new KeyValueClass(); 
     MST = new KeyValueClass(); 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    private void NotifyPropertyChanged(String propertyName = "") 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

} 

而且KeyValueClass很簡單(什麼做我需要在這裏?):

class KeyValueClass 
{ 
    private string _name; 
    private string _val; 

    public string Name 
    { 
     get 
     { 
      return _name; 
     } 
     set 
     { 
      _name = value; 
     } 
    } 
    public string Value 
    { 
     get 
     { 
      return _val; 
     } 
     set 
     { 
      _val = value; 
     } 
    } 
} 

我需要此集合中的嵌套屬性,因爲我可以使用不同語言獲取這些數據。所以我不能編碼網格的標題。

回答

0

由於您只能綁定到公共屬性您必須定義「tcc」。你TableClass和KeyValueClass類型也必須是公開的:

public partial class Home : UserControl 
{ 
    public ObservableCollection<TableClass> tcc { get; set; } 

    public Home() 
    { 
     InitializeComponent(); 
     tcc = new ObservableCollection<TableClass>(); 
     DataContext = this; 
    } 

    private void UserControl_Loaded(object sender, RoutedEventArgs e) 
    { 
     TableClass tc; 
     List<TableClass> tcl = new List<TableClass>(); 

     tcc.CollectionChanged += tcc_CollectionChanged; 

     for (int i = 0; i < 10; i++) 
     { 
      tc = new TableClass(); 

      tc.AGNR.Name = "AGNr"; 
      tc.AGNR.Value = i.ToString(); 

      tc.MNR.Name = "MNr"; 
      tc.MNR.Value = i.ToString() + " M"; 

      tc.MST.Name = "MSt"; 
      tc.MST.Value = i % 2 == 0 ? "production" : "stopped"; 

      tcc.Add(tc); 
     } 

    } 

    static void PropertyChangedHandler(object sender, PropertyChangedEventArgs e) 
    { 
     Console.WriteLine(DateTime.Now.ToString() + ", Property changed"); 
     return; 
    } 

    static void tcc_CollectionChanged(object sender, EventArgs e) 
    { 
     Console.WriteLine(DateTime.Now.ToString() + ", Collection changed"); 
     return; 
    } 
} 

public class TableClass : INotifyPropertyChanged 
{ 
    private KeyValueClass _mnr; 
    private KeyValueClass _agnr; 
    private KeyValueClass _mst; 

    public KeyValueClass MNR 
    { 
     get 
     { 
      return _mnr; 
     } 
     set 
     { 
      _mnr = value; 
      NotifyPropertyChanged("MNR"); 
     } 
    } 
    public KeyValueClass AGNR 
    { 
     get 
     { 
      return _agnr; 
     } 
     set 
     { 
      _agnr = value; 
      NotifyPropertyChanged("AGNR"); 
     } 
    } 
    public KeyValueClass MST 
    { 
     get 
     { 
      return _mst; 
     } 
     set 
     { 
      _mst = value; 
      NotifyPropertyChanged("MST"); 
     } 
    } 

    public TableClass() 
    { 
     MNR = new KeyValueClass(); 
     AGNR = new KeyValueClass(); 
     MST = new KeyValueClass(); 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    private void NotifyPropertyChanged(String propertyName = "") 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

} 

public class KeyValueClass 
{ 
    private string _name; 
    private string _val; 

    public string Name 
    { 
     get 
     { 
      return _name; 
     } 
     set 
     { 
      _name = value; 
     } 
    } 
    public string Value 
    { 
     get 
     { 
      return _val; 
     } 
     set 
     { 
      _val = value; 
     } 
    } 
} 

沒有內置類ObservableTable,所以我改變了這個在上面的示例代碼的ObservableCollection。

你也應該列添加到收集的DataGrid:

<DataGrid x:Name="tcgrid" ItemsSource="{Binding tcc, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
        AutoGenerateColumns="False"> 
    <DataGrid.Columns> 
     <DataGridTextColumn Binding="{Binding AGNR.Value, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" 
           Header="{Binding AGNR.Key, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/> 
     <DataGridTextColumn Binding="{Binding MNR.Value, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" 
           Header="{Binding MNR.Key, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/> 
     <DataGridTextColumn Binding="{Binding MST.Value, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" 
           Header="{Binding MST.Key, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/> 
    </DataGrid.Columns> 
</DataGrid> 

然後它似乎工作:

+0

嗨MM8 感謝您的答案,你的建議是讓公共財產「tcc」。之前我將它設爲私有,因爲它在不公開我的類型的情況下給出錯誤。 我仍然得到相同的錯誤_無法找到控制目標element_的FrameworkElement或FrameworkContentElement,但正如您在圖片中看到的那樣,網格的標頭爲空。 對我來說結果仍然是一個完全空白的表格。 Observable Table是從我在我的問題中引用的問題中「採取」它看起來像這樣 – moser

+0

...不能粘貼代碼在這裏。如果KeyValueClass中的屬性發生更改,我想從類中獲取的是一個通知。 – moser

+0

列標題的綁定應該是AGNR.Name等如果我嘗試這樣做,仍然是空的標題 – moser

相關問題