C# WPF使用嵌套属性将Datagrid绑定到ObservableCollection
我想将DataGrid绑定到嵌套属性的集合。 我尝试了C# WPF使用嵌套属性将Datagrid绑定到ObservableCollection,c#,wpf,data-binding,datagrid,observablecollection,C#,Wpf,Data Binding,Datagrid,Observablecollection,我想将DataGrid绑定到嵌套属性的集合。 我尝试了 但到目前为止运气不好 我得到的是一个空的DataGrid和控制台输出,如下所示: System.Windows.Data错误:2:找不到目标元素的治理FrameworkElement或FrameworkContentElement。BindingExpression:Path=AGNR.Key;DataItem=null;目标元素是“DataGridTextColumn”(HashCode=38805039);目标属性为“Header”(类
但到目前为止运气不好 我得到的是一个空的DataGrid和控制台输出,如下所示: System.Windows.Data错误:2:找不到目标元素的治理FrameworkElement或FrameworkContentElement。BindingExpression:Path=AGNR.Key;DataItem=null;目标元素是“DataGridTextColumn”(HashCode=38805039);目标属性为“Header”(类型为“Object”) tcc_采集的输出也发生了变化(但不包括PropertyChangedHandler): 2016年12月30日11:11:22,收款变更 我使用现代UI(第一层)框架。以下是我的窗口代码:
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;
}
}
KeyValueClass非常简单(我在这里需要什么?):
我需要在集合中嵌套这些属性,因为我可以用不同的语言获取这些数据。因此,我无法对网格的标题进行编码。因为您只能绑定到公共属性,所以必须定义“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;
}
}
}
public部分类主页:UserControl
{
公共可观测集合tcc{get;set;}
公共住宅()
{
初始化组件();
tcc=新的可观测集合();
DataContext=this;
}
已加载私有void UserControl_(对象发送方,RoutedEventArgs e)
{
表类tc;
List tcl=新列表();
tcc.CollectionChanged+=tcc\U CollectionChanged;
对于(int i=0;i<10;i++)
{
tc=新的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?“生产”:“已停止”;
tcc.Add(tc);
}
}
静态无效PropertyChangedHandler(对象发送方,PropertyChangedEventArgs e)
{
Console.WriteLine(DateTime.Now.ToString()+“,属性已更改”);
回来
}
静态无效tcc_集合已更改(对象发送方,事件参数e)
{
Console.WriteLine(DateTime.Now.ToString()+“,集合已更改”);
回来
}
}
公共类TableClass:INotifyPropertyChanged
{
private KeyValueClass\u mnr;
private KeyValueClass\u agnr;
private KeyValueClass_mst;
公钥值类MNR
{
收到
{
返回mnr;
}
设置
{
_mnr=数值;
通知财产变更(“MNR”);
}
}
公钥值类AGNR
{
收到
{
返回_agnr;
}
设置
{
_agnr=数值;
NotifyPropertyChanged(“AGNR”);
}
}
公钥值类MST
{
收到
{
返回mst;
}
设置
{
_mst=值;
NotifyPropertyChanged(“MST”);
}
}
公共表类()
{
MNR=新的KeyValueClass();
AGNR=新的KeyValueClass();
MST=新的KeyValueClass();
}
公共事件属性更改事件处理程序属性更改;
私有void NotifyPropertyChanged(字符串propertyName=“”)
{
if(PropertyChanged!=null)
{
PropertyChanged(这是新的PropertyChangedEventArgs(propertyName));
}
}
}
公共类KeyValueClass
{
私有字符串\u名称;
私有字符串_val;
公共字符串名
{
收到
{
返回_name;
}
设置
{
_名称=值;
}
}
公共字符串值
{
收到
{
返回值;
}
设置
{
_val=值;
}
}
}
没有内置的类ObservableTable,所以我在上面的示例代码中将这个类更改为ObservableCollection
您还应该将这些列添加到DataGrid的columns集合中:
<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>
然后它似乎起作用了:
您好mm8感谢您的回答和关于将“tcc”物业公之于众的建议。我以前将其设置为私有,因为它在没有公开我的类型的情况下给出了一个错误。我仍然会遇到同样的错误,无法为目标元素找到治理FrameworkElement或FrameworkContentElement,但是,正如您在图片中看到的,网格的标题是空的。结果对我来说仍然是一张空桌子。可观察表是从我在问题中引用的问题中“获取”的,看起来是这样的……不能在这里粘贴代码。如果KeyValueClass中的属性发生更改,我希望从该类获得通知。列标题的绑定应为AGNR.Name等。如果我尝试此操作,仍然为空标题每个列只有一个列标题,并且列标题没有DataContext,那么您希望在标题中显示哪个类的属性?一个列标题映射到多个TableClass对象,因此将标题绑定到TableClass对象的属性是没有意义的。。。
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;
}
}
}
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;
}
}
}
<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>