C#数据绑定最小测试用例中错误的更新通知 [英] Wrong update notification in C# databinding minimal test case

查看:118
本文介绍了C#数据绑定最小测试用例中错误的更新通知的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在C#中创建了一个最小的测试场景来探索数据绑定的机制。背景是:我想表明,改变绑定在数据绑定中的属性的子属性不会触发绑定对方的更新(只有更改绑定属性本身应该触发更新)!



但是我发现它在我的测试用例中,我很困惑,我的测试用例或数据绑定中的错误实际上是以这种方式工作的。测试用例非常方便:

 命名空间DatabindingMinimal 
{
//名称为$ b $的人b public class Person
{
public String Name {get;组;

public Person(String name)
{
this.Name = name;
}
}

//类暴露一个人最好的朋友
// INotifyPropertyChanged不在这里实现
public class Friends
{
public Person BestFriend {get;组;

public朋友(String bestFriendName)
{
this.BestFriend = new Person(bestFriendName);
}
}

//将Person作为父级显示为DependencyProperty
public class Parents:DependencyObject
{
public static DependencyProperty FatherProperty =
DependencyProperty.Register(Father,typeof(Person),typeof(Parents));

public Person Father
{
get {return(Person)this.GetValue(FatherProperty); }
set {this.SetValue(FatherProperty,value);
}

public Parents(String fatherName)
{
this.Father = new Person(fatherName);
}
}

//测试朋友和父母之间的数据绑定
类程序
{
static void Main(string [] args )
{
朋友f =新朋友(汉弗莱);
父母p =新父母(鲁道夫);

绑定bindBeziehungen = new Binding(BestFriend);
bindBeziehungen.Source = f;
bindBeziehungen.Mode = BindingMode.TwoWay;
BindingOperations.SetBinding(p,Parents.FatherProperty,bindBeziehungen);

f.BestFriend.Name = String.Empty; // p.Father.Name现在也设置为空b
$ b System.Console.WriteLine(f.BestFriend.Name);
System.Console.WriteLine(p.Father.Name);

// ...现在输出的两个字符串都是空的

if(Object.ReferenceEquals(f.BestFriend,p.Father))
System.Console.WriteLine(identical); //这是真的!
}
}
}

测试用例绑定了朋友类作为父母类作为目标的实例的来源。朋友课没有任何通知机制!但是改变f.BestFriend.Name属性改变p.Father.Name属性!更改绑定的BestFriend属性本身不更新任何东西(如预期):

  f.BestFriend = new Person(); // p.Father不会改变这里! 

在直接更改f.BestFriend时,引用不等于末尾!



问题:
那么,在创建绑定并在一边进行更新后,绑定属性的引用是相等的吗?



为什么更改f.BestFriend.Name完全触发更新,即使没有INotifyPropertyChanged实现?



我感觉到绑定分配一个绑定的Person属性的一个引用来匹配幕后的其他对象?有人可以清除这个问题吗?

解决方案

你所问的问题不是问题,而是一些混乱或误会,我猜。



看看你的数据绑定。这个绑定最重要的是将 p.Father 设置为与 f.BestFriend 相同的值。认为它等同于以下代码:

  p.Father = f.BestFriend; 

(好的,绑定和这个代码关于如何绑定和DependencyProperty是维持的,但在这个问题的背景下,这是一个很好的简化。)



这是什么结果?绑定初始化后, p.Father f.BestFriend 将引用相同的 Person对象。



您实际上可以用代码行替换代码中的绑定,并且具有相同的效果。



没有魔术更新如果您将名称属性设置为另一个值,例如:

  f.BestFriend。 Name = String.Empty; 

当然,您将看到与 f.BestFriend.Name 相同的值而对于 p.Father.Name ,因为 f.BestFriend p.Father 指的是相同的单个Person对象 - 你已经找到了你的代码中最后一个 if 语句的方式。



没有魔术更新属性从一个Person对象到另一个Person对象,因为你的代码再次只处理一个Person对象(而不是两个,就像你似乎假设的那样)。



关于

  f.BestFriend = new Person(); // p.Father不会改变这里! 

当然 p.Father 不会改变,你已经知道为什么。尽管 f.BestFriend 是绑定的源,但是绑定将不知道是否/何时ffestestFriend的值(该值是对Person对象的引用)因为没有通过INotifyPropertyChanged 实现,因为没有被通知。由于不通知绑定,因此它不会更新 p.Father 的值。执行这行代码之后, f.BestFriend 将引用不同的 Person对象,而不是 p.Father



基本上,你所想的一切,你所问的只是从一个误会中浮出水面。没有两个Person对象,没有绑定做更新(除了作为其初始设置的一部分),并且没有任何属性更改通知发生在所有...


I have created a minimal test scenario in C# to explore mechanism of databinding. The background is: I wanted to show that changing a sub-property of a property that is bound in databinding does NOT trigger an update to the other side of the binding (Only changing the bound property itself should trigger update)!

BUT I found that it does in my testcase and I am confused wether I have an error in my testcase or databinding actually works that way. The testcase is quite handy:

namespace DatabindingMinimal
{
    // Person with a name
    public class Person
    {
        public String Name { get; set; }

        public Person(String name)
        {
            this.Name = name;
        }
    }

    // class exposing a Person as best Friend
    // INotifyPropertyChanged is not implemented here
    public class Friends 
    {
        public Person BestFriend { get; set; }

        public Friends(String bestFriendName)
        {
            this.BestFriend = new Person(bestFriendName);
        }
    }

    // class exposing a Person as father as DependencyProperty
    public class Parents : DependencyObject
    {
        public static DependencyProperty FatherProperty =
            DependencyProperty.Register("Father", typeof(Person), typeof(Parents));

        public Person Father
        {
            get { return (Person)this.GetValue(FatherProperty); }
            set { this.SetValue(FatherProperty, value); }
        }

        public Parents(String fatherName)
        {
            this.Father = new Person(fatherName);
        }
    }

    // test the databinding between Friends and Parents
    class Program
    {
        static void Main(string[] args)
        {
            Friends f = new Friends("Humphrey");
            Parents p = new Parents("Rudolph");

            Binding bindBeziehungen = new Binding("BestFriend");
            bindBeziehungen.Source = f;
            bindBeziehungen.Mode = BindingMode.TwoWay;
            BindingOperations.SetBinding(p, Parents.FatherProperty, bindBeziehungen);

            f.BestFriend.Name = String.Empty;   // the p.Father.Name is now set Empty as well

            System.Console.WriteLine(f.BestFriend.Name);
            System.Console.WriteLine(p.Father.Name);

            // ... Both Strings are empty in output now!

            if (Object.ReferenceEquals(f.BestFriend, p.Father))
                System.Console.WriteLine("identical");    // this is true here!
        }
    }
}

The testcase binds the friends class as source to an instance of the parents class as target. The friends class does NOT have any notification mechanism! But changing the f.BestFriend.Name property DOES CHANGE the p.Father.Name property! Changing the bound BestFriend property itself does not update anything (as expected):

f.BestFriend = new Person("");    // p.Father does not change here!

Also the references are not equal at the end when changing f.BestFriend directly!

Question: So, is it normal that references of bound properties are equal after creating the binding and doing an update at one side?

Why does changing f.BestFriend.Name trigger an update at all, even without INotifyPropertyChanged implemented?

I have the feeling that the binding assigns one reference of a bound Person property to match the other behind the scenes?! Can someone clear this issue?

解决方案

The problem you are ask about is not a problem, but rather a result of some confusion or misunderstanding, i guess.

Look at your data binding. The most important thing this binding does is setting p.Father to the same value as f.BestFriend. Think of it being equivalent to the following code:

p.Father = f.BestFriend;

(Okay, the binding is not exactly equivalent with this code with regard to how the binding and the DependencyProperty are maintained. But within the context of this question this is a good-enough simplification.)

What is the result of this? After the binding is initialized, p.Father and f.BestFriend will refer to the same Person object.

You can actually replace the binding in your code with the code line above and experience the very same effect.

There is no magic update (or magic update notification) if you set the Name property to another value like:

f.BestFriend.Name = String.Empty; 

Of course you will see the same value for f.BestFriend.Name and for p.Father.Name, because both f.BestFriend and p.Father refer to the very same single Person object -- which by the way you already found out with the last if statement in your code.

There is no magic update of properties from one Person object to another Person object, because, again, your code deals only with one single Person object (and not with two, as you seem to assume).

Regarding

f.BestFriend = new Person("");    // p.Father does not change here!

of course p.Father does not change, and you already know why. Although f.BestFriend is the source of the binding, the binding will not know if/when the value of f.BestFriend (the value being a reference to a Person object) changes, since it is not being notified due to the lack of a INotifyPropertyChanged implementation. Since the binding is not notified, it won't update the value of p.Father. After executing this line of code, f.BestFriend will refer to a different Person object than p.Father.

Essentially, all what you wonder about and what you ask about just sprung from a misunderstanding. There are no two Person objects, and there is no binding doing an update (except as part of its initial setup), and there is no property change notification happening at all...

这篇关于C#数据绑定最小测试用例中错误的更新通知的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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