【问题标题】:How do I pass changes from source in a TwoWay binding?如何在双向绑定中传递来自源的更改?
【发布时间】:2011-09-19 15:49:11
【问题描述】:

我创建了一个包含依赖属性“Text”的自定义 TextBox 控件(但不是从 TextBox 派生的)。

我已经添加了 this 的一个实例,并使用 TwoWay 绑定将它绑定到我的视图模型上的一个属性。

如何在我的自定义 TextBox 控件中更新 Text 属性,以便将更改传播到视图模型上的属性?

如果我在自定义控件上设置“文本”属性,它将替换绑定,使视图模型上的属性为空。

我原以为这很简单,但我不知道该怎么做(标准的 TextBox 控件必须这样做!)

干杯

编辑:

自定义控件:

public class SampleCustomControl : CustomControl
{
    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register("Text", typeof(string), typeof(SampleCustomControl), new PropertyMetadata(null));

    public void Update()
    {
        // This replaces my binding, I want it to pass the new value 
        // through to the "SomeProperty" two way binding.
        Text = "some value";
    }

}

用法:

<Controls:SampleCustomControl Text="{Binding SomeProperty, Mode=TwoWay}" />

【问题讨论】:

  • 所有 DependencyProperty 更新都是通过幕后的 SetValue 来触发绑定上的更改事件。您通常会为您的 DP 添加一个 set/get 对(仅供您自己使用),它也调用 GetValue/SetValue。您能否展示您的 XAML 和代码以进行控制和使用,因为它应该是微不足道的。设置你的文本属性不应该改变绑定。
  • 我正在设置一个 Text 属性,它本身会调用 SetValue 方法,但这正在替换绑定 - 我将添加一些代码来演示它

标签: silverlight silverlight-4.0 mvvm


【解决方案1】:

您需要在metadata of your dependency property 中添加属性更改回调。

当 Text 属性发生变化(从任一侧)时,将触发此回调。您可以使用从这里传入的值来更新您为显示文本而构建的自定义 UI。

更新: 回应你关于这是什么的评论。由于您的示例代码太模糊而无法测试,因此这是我用来测试您的问题的代码。

public class TestControl : ContentControl
{
    private TextBlock _tb;

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();
        _tb = new TextBlock();
        _tb.Text = Text;
        this.Content = _tb;
        _tb.MouseLeftButtonDown += new MouseButtonEventHandler(_tb_MouseLeftButtonDown);
    }

    void _tb_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        Update();
    }

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register("Text", typeof(string), typeof(TestControl), new PropertyMetadata(string.Empty, OnTextChanged));

    public void Update()
    {
        // This replaces my binding, I want it to pass the new value 
        // through to the "SomeProperty" two way binding.
        Text = "some value";
    }

    public static void OnTextChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        ((TestControl)sender).UpdateText((string)e.NewValue);
    }

    protected void UpdateText(string text)
    {
        if (_tb != null) _tb.Text = text;
    }
}

然后,我使用双向绑定将控件上的 Text 属性绑定到视图模型。当我单击视图中的文本时,视图和视图模型都会使用新文本“某个值”进行更新。如果我更新视图模型中的值(并引发属性更改事件),则视图和控件中的值会更新,因此绑定仍然有效。

您的示例中肯定还有一些其他缺失的部分。

【讨论】:

  • 问题不在于在绑定更改时更新我的​​自定义控件,而是更新自定义控件中的值以通过绑定传递到视图模型。
  • 在桌子上打脸你说得对,有些东西不见了 - 在 UserControl 的 XAML 中,我已将控件的 DataContext 设置为 RelativeSource=Self,即意味着 Text DP 上的 TwoWay 绑定试图绑定到控件本身而不是 ViewModel 上的属性,不完全确定该行为是否出色,但我已经删除了 DataContext,给定控件的根 x:Name并使用 ElementName 绑定在我的 UserControl 中绑定控件,现在一切正常。将来我必须更加注意所有这些都清楚的输出窗口! :)
【解决方案2】:

只要您的绑定属性设置为 TwoWay 并且您已经公开了 getter 和 setter,那么您在 TextBox 中输入的文本就会发送到 ViewModel。我相信当您失去该控制的焦点时会发生实际发送,但我相信。

【讨论】:

  • 我没有使用实际的 TextBox,我创建了一个自定义控件,希望支持双向绑定。
猜你喜欢
  • 2012-09-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-19
  • 2020-02-02
  • 1970-01-01
  • 1970-01-01
  • 2011-07-31
相关资源
最近更新 更多