设置DataContext后WPF依赖属性两种方式绑定不起作用[重复]
Posted
技术标签:
【中文标题】设置DataContext后WPF依赖属性两种方式绑定不起作用[重复]【英文标题】:WPF Dependency Property Two way binding not working after DataContext is set [duplicate] 【发布时间】:2021-09-14 02:10:34 【问题描述】:我有一个 ComboBox,它的 ItemSource 集合可以从应用程序的其他部分更改,这个 ComboboBox 可以用于应用程序的多个位置。因此,为了集中这一点,我创建了一个仅包含组合框的用户控件,并将其数据源设置为 viewmodel,并公开了一个用于绑定的依赖属性。但是依赖属性不会更新组合框项目选择的绑定属性。
这是我提取的示例代码
//My base Model for Combobox data
public class MyModel
public int Id get; set;
public string Text get; set;
//Base class for View Models to notify property change
public class BaseViewModel : INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged = (sender, e) =>;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
//View model for user control that contains combobox
public class MyModelViewModel : BaseViewModel
private ObservableCollection<MyModel> _mymodelCollection;
public ObservableCollection<MyModel> MyModelCollection
get return _mymodelCollection;
set
_mymodelCollection = value;OnPropertyChanged();
public MyModelViewModel()
MyModelCollection = new ObservableCollection<MyModel>
new MyModel
Id = 1, Text = "Project 1"
,
new MyModel
Id = 2, Text = "Project 2"
,
new MyModel
Id = 3, Text = "Project 3"
;
//View model for parent window that contains combobox user control
public class TestWindowViewModel : BaseViewModel
private int _myModelId;
public int MyModelIdInWindow
get return _myModelId;
set
_myModelId = value; OnPropertyChanged();
//debug code
Console.WriteLine(value);
//User Control for reusability
<UserControl x:Class="SimpleWPF.Control.CommonControl"
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"
xmlns:local="clr-namespace:SimpleWPF.Control"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<ComboBox
x:Name="cmbList"
Grid.Row="0"
Grid.Column="0"
ItemsSource="Binding MyModelCollection, Mode=OneWay"
DisplayMemberPath="Text"
SelectedValuePath="Id"
SelectionChanged="cmbList_SelectionChanged"
/>
</Grid>
</UserControl>
//User Control Code Behind with exposed MyModelId DP
public partial class CommonControl : UserControl
private bool _isInternalUpdate = false;
public int MyModelId
get return (int)GetValue(MyModelIdProperty);
set SetValue(MyModelIdProperty, value);
// Using a DependencyProperty as the backing store for BranchId. This enables animation, styling, binding, etc...
public static readonly DependencyProperty MyModelIdProperty =
DependencyProperty.Register("MyModelId", typeof(int), typeof(CommonControl),
new FrameworkPropertyMetadata(int.MinValue,
FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, MyModelIdPropertyChanged,
null, false, UpdateSourceTrigger.PropertyChanged));
public CommonControl()
InitializeComponent();
this.DataContext = new MyModelViewModel();
private void cmbList_SelectionChanged(object sender, SelectionChangedEventArgs e)
if(cmbList.SelectedValue != null)
_isInternalUpdate = true;
MyModelId = (int)cmbList.SelectedValue;
_isInternalUpdate = false;
private static void MyModelIdPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
if (d is CommonControl branchComboBox)
branchComboBox.UpdateBranch();
private void UpdateBranch()
if (!_isInternalUpdate)
cmbList.SelectedValue = MyModelId;
终于在窗口中
<ctrl:CommonControl MyModelId="Binding MyModelIdInWindow, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged"/>
即使在用户控件中 MyModelId DP 值发生更改,MyModelIdInWindow 属性也不会更新
【问题讨论】:
UserControl 和它的任何一个子元素都不应该设置它们的 DataContext。不应有应用程序的其余部分不知道的私有视图模型对象。而是在控件的 XAML 中使用 RelativeSource 绑定。 【参考方案1】:您需要实现INotifyCollectionChanged
接口而不是INotifyPropertyChanged
。
如果您希望在单个对象属性更改时更新网格,则每个包含的对象都必须实现 INotifyPropertyChanged 接口。 INotifyCollectionChanged 是集合应实现的接口,用于通知添加和删除事件
【讨论】:
感谢您的建议,我也应该实施它,但我想这并没有导致实际问题。是吗? @BhubanShrestha 其实我觉得是……【参考方案2】:解决方法是不要为 UserControl 设置 DataContext
public CommonControl()
InitializeComponent();
(this.Content as FrameworkElement).DataContext = new MyModelViewModel();
//this.DataContext = new MyModelViewModel();
感谢@jerrynixon 关于Two-way binding inside a XAML User Control的博客
【讨论】:
以上是关于设置DataContext后WPF依赖属性两种方式绑定不起作用[重复]的主要内容,如果未能解决你的问题,请参考以下文章
[翻译] WPF 中用户控件 DataContext/Binding 和依赖属性的问题