数据绑定链 [英] Chain of DataBinding

查看:98
本文介绍了数据绑定链的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在追踪DataBinding

I am trying to do follow DataBinding

Property -> DependencyProperty -> Property

但我有麻烦。
例如
我们有简单的类与两个属性实现INotifyPropertyChanged:

But i have trouble. For example, We have simple class with two properties implements INotifyPropertyChanged:

public class MyClass : INotifyPropertyChanged
    {
        private string _num1;
        public string Num1
        {
            get { return _num1; }
            set
            {
                _num1 = value;
                OnPropertyChanged("Num1");
            }
        }

        private string _num2;
        public string Num2
        {
            get { return _num2; }
            set
            {
                _num2 = value;
                OnPropertyChanged("Num2");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged(string e)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(e));
        }
    }

在xaml中声明的TextBlock:

And TextBlock declared in xaml:

<TextBlock Name="tb" FontSize="20" Foreground="Red" Text="qwerqwerwqer" />

现在可以尝试将Num1绑定到tb.Text:

Now lets trying to bind Num1 to tb.Text:

private MyClass _myClass = new MyClass();
        public MainWindow()
        {
            InitializeComponent();

            Binding binding1 = new Binding("Num1")
                                   {
                                       Source = _myClass, 
                                       Mode = BindingMode.OneWay
                                   };

            Binding binding2 = new Binding("Num2")
            {
                Source = _myClass,
                Mode = BindingMode.TwoWay
            };

            tb.SetBinding(TextBlock.TextProperty, binding1);

            //tb.SetBinding(TextBlock.TextProperty, binding2);


            var timer = new Timer(500) {Enabled = true,};

            timer.Elapsed += (sender, args) => _myClass.Num1 += "a";

            timer.Start();


        }

效果很好。但是如果我们取消注释这个字符串

It works well. But if we uncomment this string

tb.SetBinding(TextBlock.TextProperty, binding2);

然后TextBlock什么都不显示。 DataBinding不起作用

then TextBlock display nothing. DataBinding doesn't work! How can i to do what i want?

推荐答案

问题是, SetBinding 调用清除任何先前的绑定。所以当你设置绑定到 Num2 时,你将清除绑定到 Num1 。这是因为依赖属性绑定不能有多个来源 - 它会如何知道要使用哪个来源? (当然,这忽略了 MultiBinding 的使用,但这不会在这种情况下帮助您)。

The problem is that the SetBinding call clears out any previous bindings. So when you set a binding to Num2, you are clearing out the binding to Num1. This happens because a dependency property binding cannot have multiple sources- how would it know which one to use? (Of course, this ignores the usage of a MultiBinding, but that's not going to help you in this scenario).

您可以这样做的方法是使 MyClass a DependencyObject Num1 Num2 依赖关系属性。然后,您可以将 Num2 绑定到 TextBox 文本属性>,而 Num2 将在文本从 Num1 收到更新时更新。

The way you can do this is to make MyClass a DependencyObject and Num1 and Num2 dependency properties. Then you can bind Num2 to the Text property of the TextBox, and Num2 will be updated whenever the text receives an update from Num1.

一张照片值得一千字,你想做的是左边显示的。您需要做的是显示在右侧:

A picture is worth a thousand words- what you're trying to do is shown on the left. What you need to do is shown on the right:

替代文本http://img339.imageshack.us/img339/448/twosources.png

决定尝试这样做,以确保我的逻辑是健全的,实际上它有效,但有一些技巧。对于初学者,这里是新的 MyClass 代码:

Decided to try this out to ensure my logic was sound, and indeed it works, but there are some tricks. For starters, here is the new MyClass code:

public class MyClass : FrameworkElement
{
    public static readonly DependencyProperty Num1Property =
        DependencyProperty.Register("Num1", typeof(string), typeof(MyClass));

    public static readonly DependencyProperty Num2Property =
        DependencyProperty.Register("Num2", typeof(string), typeof(MyClass));

    public string Num1
    {
        get { return (string)GetValue(Num1Property); }
        set { SetValue(Num1Property, value); }
    }

    public string Num2
    {
        get { return (string)GetValue(Num2Property); }
        set { SetValue(Num2Property, value); }
    }
}

这里没什么可怕的,只是替换了你的 INotifyPropertyChanged DependencyProperty 。现在我们来看看窗口代码:

Nothing scary here, just replaced your INotifyPropertyChanged with DependencyProperty. Now let's check out the window code-behind:

public partial class DataBindingChain : Window
{
    public MyClass MyClass
    {
        get;
        set;
    }

    public DataBindingChain()
    {
        MyClass = new MyClass();

        InitializeComponent();

        Binding binding1 = new Binding("Num1")
        {
            Source = MyClass,
            Mode = BindingMode.OneWay
        };

        Binding binding2 = new Binding("Text")
        {
            Source = tb,
            Mode = BindingMode.OneWay
        };

        tb.SetBinding(TextBlock.TextProperty, binding1);
        MyClass.SetBinding(MyClass.Num2Property, binding2);

        var timer = new Timer(500) { Enabled = true, };

        timer.Elapsed += (sender, args) => Dispatcher.Invoke(UpdateAction, MyClass);

        timer.Start();
    }

    Action<MyClass> UpdateAction = (myClass) => { myClass.Num1 += "a"; };
}

这是魔法发生的地方:我们设置了两个绑定。第一个绑定 TextBlock.Text Num1 ,第二个绑定 Num2 TextBlock.Text 。现在我们有一个场景,就像我向你展示的图像的右侧 - 一个数据绑定链。另一个魔力是,我们不能在不同的线程上更新$ code> Num1 属性,而不是创建跨线程异常的线程。为了绕过这个,我们只需使用 Dispatcher 在UI线程上调用更新。

This is where the magic happens: we set up two bindings. The first binds the TextBlock.Text to Num1, the second binds Num2 to the TextBlock.Text. Now we have a scenario like the right side of the picture I showed you- a data-binding chain. The other magic is that we cannot update the Num1 property on a different thread from the one it was created on- that would create a cross-thread exception. To bypass this, we simply invoke an update onto the UI thread using the Dispatcher.

最后,XAML用于演示:

Finally, the XAML used for demonstration:

<Window x:Class="TestWpfApplication.DataBindingChain"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="DataBindingChain" Height="300" Width="300"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <TextBlock Name="tb" Grid.Row="0" FontSize="20" Foreground="Red"/>
    <TextBlock Name="tb2" Grid.Row="1" FontSize="20" Foreground="Blue" Text="{Binding MyClass.Num2}"/>
</Grid>

瞧瞧!成品:

alt text http:// img163 .imageshack.us / img163 / 6114 / victorynf.png

这篇关于数据绑定链的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆