C# 嵌套数据网格的SelectedValue绑定不';ItemsSource不工作,而ItemsSource不工作
我有一个C# 嵌套数据网格的SelectedValue绑定不';ItemsSource不工作,而ItemsSource不工作,c#,wpf,data-binding,datagrid,user-controls,C#,Wpf,Data Binding,Datagrid,User Controls,我有一个DataGrid在一个UserControl中,而这个UserControl又在另一个UserControl中。这是由于项目的其他需要,我不能更改这个嵌套的体系结构。我正在将Person类的列表绑定到此DataGrid。这是一个没有使用VM的简化版本,但在我的实际项目中,我使用的是VM 使用数据网格的MyUserControl: 第二个UserControl包含上述控件: 主窗口 在我的主窗口中,我绑定我的人员列表以及所选人员实例,如下所示: <Grid> <l
DataGrid
在一个UserControl
中,而这个UserControl又在另一个UserControl
中。这是由于项目的其他需要,我不能更改这个嵌套的体系结构。我正在将Person
类的列表绑定到此DataGrid
。这是一个没有使用VM
的简化版本,但在我的实际项目中,我使用的是VM
使用数据网格的MyUserControl
:
第二个UserControl
包含上述控件:
主窗口
在我的主窗口中,我绑定我的人员
列表以及所选人员
实例,如下所示:
<Grid>
<local:UCDisplay>
<local:UCDisplay.MyDataGrid>
<local:UCDataGrid ItemsSource="{Binding People}"
SelectedValue="{Binding SelectedPerson, UpdateSourceTrigger=PropertyChanged}"
RoutedDataGridDoubleClick="UCDataGrid_RoutedDataGridDoubleClick"/>
</local:UCDisplay.MyDataGrid>
</local:UCDisplay>
</Grid>
代码隐藏:
public partial class UCDataGrid : UserControl
{
public event RoutedEventHandler RoutedDataGridDoubleClick;
public UCDataGrid()
{
InitializeComponent();
}
public static readonly DependencyProperty ItemsSourceProperty = DependencyProperty.Register("ItemsSource", typeof(object), typeof(UCDataGrid), new PropertyMetadata(null));
public object ItemsSource
{
get { return GetValue(ItemsSourceProperty); }
set { SetValue(ItemsSourceProperty, value); }
}
public static readonly DependencyProperty SelectedValueProperty = DependencyProperty.Register("SelectedValue", typeof(object), typeof(UCDataGrid), new PropertyMetadata(null));
public object SelectedValue
{
get { return GetValue(SelectedValueProperty); }
set { SetValue(SelectedValueProperty, value); }
}
private void MyDg_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
RoutedDataGridDoubleClick?.Invoke(this, new RoutedEventArgs());
}
}
public partial class MainWindow : Window, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}
private List<Person> people;
public List<Person> People
{
get => people;
set => SetField(ref people, value);
}
private Person selectedPerson;
public Person SelectedPerson
{
get => selectedPerson;
set => SetField(ref selectedPerson, value);
}
public MainWindow()
{
InitializeComponent();
People = GetPeople();
DataContext = this;
}
private void UCDataGrid_RoutedDataGridDoubleClick(object sender, RoutedEventArgs e)
{
}
private List<Person> GetPeople()
{
return new List<Person>
{
new Person() { Name = "A" },
new Person() { Name = "B" },
new Person() { Name = "C" }
};
}
public class Person
{
public string Name { get; set; }
}
}
public分部类主窗口:窗口,INotifyPropertyChanged
{
公共事件属性更改事件处理程序属性更改;
受保护的无效OnPropertyChanged(字符串propertyName)
{
PropertyChanged?.Invoke(这是新的PropertyChangedEventArgs(propertyName));
}
受保护的布尔设置字段(参考T字段,T值,[CallerMemberName]字符串propertyName=null)
{
if(EqualityComparer.Default.Equals(字段,值))返回false;
字段=值;
OnPropertyChanged(propertyName);
返回true;
}
私人名单;
公众人物名单
{
get=>人;
set=>SetField(参考人员,值);
}
私人选择的人;
公众人士
{
get=>selectedPerson;
set=>SetField(参考selectedPerson,值);
}
公共主窗口()
{
初始化组件();
People=GetPeople();
DataContext=this;
}
私有void UCDataGrid\u路由数据网格双击(对象发送方,路由数据目标e)
{
}
私有列表GetPeople()
{
返回新列表
{
新人(){Name=“A”},
新人(){Name=“B”},
新人(){Name=“C”}
};
}
公共阶层人士
{
公共字符串名称{get;set;}
}
}
同样,在现实中,我使用的是VM
,这只是为了让事情变得简单
现在,当我运行此命令时,我可以很好地显示列表内容。但是,当我双击我的DataGrid
中的一个项目时,在我的主窗口中相应的“代码隐藏”中,SelectedPerson
保持null
,尽管其绑定与人员
列表相同。我通过在主代码后面使用断点来确认这一点:
但是如果我调试并看到最里面的UserControl
的代码后面的值,您会看到那里的SelectedValue
具有正确的selecteditems值
那么我做错了什么?为什么我不能绑定SelectedValue
,虽然我的绑定方式与ItemsSource
完全相同,但后者可以工作?SelectedValue
应该与SelectedValuePath
一起使用。您应该改用SelectedItem
除此之外,您还缺少一个双向的绑定。通过双向显式声明SelectedItem
绑定
<DataGrid x:Name="MyDg"
ItemsSource="{Binding ItemsSource,
RelativeSource={RelativeSource AncestorType=UserControl}}"
SelectedItem="{Binding SelectedItem,
RelativeSource={RelativeSource AncestorType=UserControl}, Mode=TwoWay}"/>
另外请注意,在所有绑定中设置UpdateSourceTrigger=PropertyChanged
是毫无意义的。谢谢!不知何故,我认为双向绑定是默认的,如果未指定,这就是绑定。我想我错了。
<Grid>
<local:UCDisplay>
<local:UCDisplay.MyDataGrid>
<local:UCDataGrid ItemsSource="{Binding People}"
SelectedValue="{Binding SelectedPerson, UpdateSourceTrigger=PropertyChanged}"
RoutedDataGridDoubleClick="UCDataGrid_RoutedDataGridDoubleClick"/>
</local:UCDisplay.MyDataGrid>
</local:UCDisplay>
</Grid>
public partial class MainWindow : Window, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected bool SetField<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
field = value;
OnPropertyChanged(propertyName);
return true;
}
private List<Person> people;
public List<Person> People
{
get => people;
set => SetField(ref people, value);
}
private Person selectedPerson;
public Person SelectedPerson
{
get => selectedPerson;
set => SetField(ref selectedPerson, value);
}
public MainWindow()
{
InitializeComponent();
People = GetPeople();
DataContext = this;
}
private void UCDataGrid_RoutedDataGridDoubleClick(object sender, RoutedEventArgs e)
{
}
private List<Person> GetPeople()
{
return new List<Person>
{
new Person() { Name = "A" },
new Person() { Name = "B" },
new Person() { Name = "C" }
};
}
public class Person
{
public string Name { get; set; }
}
}
<DataGrid x:Name="MyDg"
ItemsSource="{Binding ItemsSource,
RelativeSource={RelativeSource AncestorType=UserControl}}"
SelectedItem="{Binding SelectedItem,
RelativeSource={RelativeSource AncestorType=UserControl}, Mode=TwoWay}"/>
public static readonly DependencyProperty SelectedItemProperty =
DependencyProperty.Register(
nameof(SelectedItem), typeof(object), typeof(UCDataGrid),
new FrameworkPropertyMetadata(
null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public object SelectedItem
{
get { return GetValue(SelectedItemProperty); }
set { SetValue(SelectedItemProperty, value); }
}