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

C# WPF依赖项属性已更改,但未在绑定中生效,c#,wpf,mvvm,dependency-properties,C#,Wpf,Mvvm,Dependency Properties,我遇到了一个我以前发布过的问题。我仍然在努力解决这个问题,所以我试图在一个较小的代码设置中解决它 问题是: 我将dependency属性绑定到view model,它不会使用viewmodel的更改值@construction time更新viewmodel 绑定似乎是正确的,因为在应用程序启动后更改XAML中的值(依赖于XAML热重载)会使用更改更新视图模型 我可以通过以下设置重现该问题: 主窗口: <Grid> <local:UserControl1

我遇到了一个我以前发布过的问题。我仍然在努力解决这个问题,所以我试图在一个较小的代码设置中解决它

问题是:

我将dependency属性绑定到view model,它不会使用viewmodel的更改值@construction time更新viewmodel

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

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

主窗口:

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

<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>
UserControl视图模型:

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时(使用热重新加载),更新顺序是:

  • 首先设置viewmodel的setter
  • 然后,OnPropertyChanged回调启动
  • 结果是,更改的值显示在UI上
这与施工时的情况相反。那么顺序是:

  • OnPropertyChanged回调将激发
  • 视图模型的setter已设置
  • 结果是,默认值显示在UI上(如原版所述)
这真的很奇怪。因为当属性更改回调触发时(在启动期间),我可以将
DependencyObject
强制转换回我的UserControl并检查其数据上下文。此时数据上下文为空

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

  • 因此,步骤1是将文本“MyChanged text”设置为dependency属性
  • 步骤2是将视图模型作为datacontext连接到MyUserControl
  • 第3步是计算绑定,在本例中,绑定(onewaytosource)获得初始同步,但使用旧值

对我来说,这看起来像WPF中的一个bug

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

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

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


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


一个解释不同模式的小结在下面的答案中

不清楚UserControl中发生了什么-它的示例代码是incomplete@AShthx,也添加了代码。是什么触发了PropertyChangedCallback?主窗口中控件的实例化:
SomeText=“My changed text”
“ViewModel实现INotifyPropertyChanged接口以支持绑定”-ViewModel不必实现任何接口来支持bindingsHi thx尝试,但绑定不涉及文本框。绑定(OneWayToSourceone)是从我的用户控件到我的viewmodel的绑定。将其设为双向绑定还将允许viewmodel更新我的依赖项属性(我不希望这样)。
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; }
}