WPF 依赖项属性已更改,但在绑定中未生效



我遇到了一个问题,我之前在这里发布了这个问题。我仍在为这个问题而苦苦挣扎,所以我试图在较小的代码设置中分解它。

问题:

我有一个依赖属性绑定到视图模型,它不会@construction时间使用更改的值更新视图模型。

绑定似乎是正确的,因为在应用程序启动后更改 XAML 中的值(依赖于 xaml 热重载(确实会使用更改更新视图模型。

我可以通过以下设置重现该问题:

主窗口:

<Grid>
<local:UserControl1 
SomeText="My changed text" 
DataContext="{Binding UserControlViewModel}"/>
</Grid>

主视图模型:

public class MainViewModel
{
public UserControlViewModel UserControlViewModel { get; set; }
public MainViewModel()
{
UserControlViewModel = new UserControlViewModel();
}
}

用户控件:

<UserControl.Resources>
<Style TargetType="local:UserControl1">
<Setter Property="SomeText" Value="{Binding MyText, Mode=OneWayToSource}"></Setter>
</Style>
</UserControl.Resources>
<Grid>
<TextBlock Text="{Binding MyText}"></TextBlock>
</Grid>

用户控件代码隐藏:

public static readonly DependencyProperty SomeTextProperty = DependencyProperty.Register(
nameof(SomeText),
typeof(string),
typeof(UserControl1),
new PropertyMetadata("default text", PropertyChangedCallback));
public string SomeText { get; set; }
private static void PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// first and only update: 'default text' => 'My changed text'
}
public UserControl1()
{
InitializeComponent();
}

用户控件视图模型:

public class UserControlViewModel
{
// Setter is called with 'default text'
// AFTER the property changed callback is triggered with updated text
public string MyText { get; set; }
}

当我运行应用程序时,将显示文本"默认文本",而我期望"我更改的文本"。

然后,当我在 XAML 中更改 SomeText 属性时,我再次看到更改的回调触发,因此我看到视图模型资源库得到更新。这次使用更改的值。因此,绑定似乎工作正常,但在启动期间,它无法使用(已知(更改的值更新视图模型。

任何人都可以解释导致此问题的原因吗?有没有办法解决这个问题?

更新

我刚刚发现,当我更改 XAML(使用热重载(时,更新顺序为:

  • 首先设置视图模型的设置器
  • 然后OnPropertyChanged 回调触发。
  • 结果是更改的值显示在 UI 上

这与施工时的情况相反。那么顺序是:

  • OnPropertyChanged 回调触发
  • 视图模型的设置器已设置。
  • 结果是默认值显示在 UI 上(如原始问题中所述(

这其实真的很奇怪。因为当属性更改回调触发(在启动期间(时,我可以将DependencyObject强制转换为我的 UserControl 并检查其数据上下文。数据上下文此时为

我之前对热重载的实验证明,最终绑定工作完美。

  • 因此,步骤 1 是将文本"我更改的文本"设置为依赖项属性。
  • 步骤 2 是将视图模型作为数据上下文连接到 MyUserControl
  • 步骤 3 是评估绑定,在这种情况下,绑定(onewaytosource(获取其初始同步,但使用旧值

对我来说,这看起来像是 WPF 中的一个错误。

您的用例使用了错误的绑定模式。

指定 OneWayToSource 时,将只允许数据从文本框流向 ViewModel 中的属性,因为源是 MyText 属性。

尝试删除 Mode=OneWayToSource,或者如果您希望从 View 和 ViewModel 更新文本,请使用 TwoWay。(IIRC 双向是文本框控件的默认模式(。

另外,您的 ViewModel 是否实现了 INotifyPropertyChanged 接口以支持绑定?

解释不同模式的小摘要在此SO答案中

最新更新