【问题标题】:WPF CustomControl unable to bind dependency property two way to view modelWPF CustomControl无法以两种方式绑定依赖属性来查看模型
【发布时间】:2017-03-13 14:43:42
【问题描述】:

我创建了一个自定义控件,其依赖属性绑定到视图模型属性。

<wpf1:CustomTextBox StringProperty="{Binding StringValue}" />

视图模型如下所示

public class ViewModel : INotifyPropertyChanged
{
    public string StringValue
    {
        get { return m_stringValue; }
        set
        {
            m_stringValue = value;
            OnPropertyChanged("StringValue");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    private string m_stringValue;
}

DataContext在后面的代码中设置

public partial class MainWindow
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = ViewModel = new ViewModel();
    }

    public ViewModel ViewModel { get; set; }
}

依赖属性的绑定方式默认是两种方式

    public static readonly DependencyProperty StringPropertyProperty =
        DependencyProperty.Register(
            "StringProperty",
            typeof(string),
            typeof(CustomTextBox),
            new FrameworkPropertyMetadata
            {
                BindsTwoWayByDefault = true,
                DefaultUpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
                PropertyChangedCallback = PropertyChangedCallback
            });

现在我遇到了问题,当视图模型属性 StringValue 更改时,自定义控件会收到通知,但是当我更改依赖属性的值时,视图模型的值不会更改。

    private static void PropertyChangedCallback(DependencyObject dO,
    DependencyPropertyChangedEventArgs e)
    {
        var textBox = (CustomTextBox) dO;
        if (textBox.StringProperty == null)
            return;
        DoSomething(textBox.StringProperty)
        textBox.StringProperty = null;
    }

如果我将视图模型值设置为“某个值”,我希望自定义控件使用该字符串并将其重置为 null。到目前为止,这可行,但视图模型值未同步,并且保持“某个值”而不是 null。任何想法如何做到这一点?为什么双向绑定不起作用?

谢谢。

【问题讨论】:

  • O/T,但public ViewModel ViewModel { get { return DataContext as ViewModel; } set { DataContext = value; } } 让您不必担心保持类型属性与DataContext 同步。

标签: c# wpf data-binding dependency-properties


【解决方案1】:

这一行

textBox.StringProperty = null;

移除之前定义的绑定 (&lt;wpf1:CustomTextBox StringProperty="{Binding StringValue}" /&gt;)

尝试使用

textBox.SetCurrentValue(StringPropertyProperty, null);

【讨论】:

  • 感谢您的提示。不幸的是,即使工具提示也表明 SetCurrentValue 正是我正在寻找的,但这也不起作用(与 SetValue 相同)。如果我在像 Textproperty 这样的内置属性上使用它而不是我的依赖属性,它的行为与预期完全一样。好像有区别……
  • 澄清 - 如果支持从目标到源的数据传输,SetValue 不会删除属性上的绑定集,即 TwoWayOneWayToSource 绑定模式。
【解决方案2】:

您的代码无法按预期工作的原因是您正在为 StringProperty 分配新值,同时仍在处理对该属性的先前更改。我真的不知道其背后的机制(可能是某种机制旨在防止潜在的无限递归调用?),但我 100% 认为这是罪魁祸首。

要解决您的问题,将新的值分配推迟到您的处理程序返回控件就足够了,这可以通过使用与您的控件关联的Dispatcher 轻松实现:

private static void PropertyChangedCallback(DependencyObject dO,
    DependencyPropertyChangedEventArgs e)
{
    var textBox = (CustomTextBox) dO;
    if (textBox.StringProperty == null)
        return;
    DoSomething(textBox.StringProperty)
    //following lambda will be queued for execution rather than executed immediately
    //and is guaranteed to be executed after this handler has finished
    textBox.Dispatcher.InvokeAsync(() => textBox.StringProperty = null);
}

如果您使用的是 4.5 之前的 .NET 版本,则需要改用 Dispatcher.BeginInvoke 方法。

【讨论】:

  • 完美运行!非常感谢。
猜你喜欢
  • 1970-01-01
  • 2012-11-04
  • 2012-11-08
  • 2021-09-14
  • 1970-01-01
  • 1970-01-01
  • 2011-12-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多