现在的位置: 首页 > 综合 > 正文

databinding ObservableCollection易错之一:重新New一个新地址,不会自动通知UI

2019年04月16日 ⁄ 综合 ⁄ 共 3193字 ⁄ 字号 评论关闭

    刚用Databinding的同学会经常有各种各样失败的原因。最近在对Databinding对Collection做绑定的时候,犯了一个错误,感觉挺常见的,分享记录下:很多初学者大概以为ObservableCollection<>  任何改变的消息都会发一个事件告诉UI,但实际上是对ObservableCollection<>重新new一个地址,它并不会把新New 的地址发消息告诉UI,UI记录的source
target的地址依然是之前的,除非你自己发消息告诉UI。

     用一个简单的Databinding的例子说明,如下:

    在UI 的ListBox绑定显示一个ObservableCollection<>,当点击了testButton后,在后台修改数据并显示。

 

点击testButton后

具体代码:

In XAML:

<UserControl x:Class="DataBindingReference.MainPage"

xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"

mc:Ignorable="d"

d:DesignHeight="300" d:DesignWidth="400">

<Grid x:Name="LayoutRoot"
Background
="White">

<ListBox ItemsSource="{Binding
Path
=MClassBs}" DisplayMemberPath="MText"/>

<Button x:Name="textButton"
Content
="testButton" VerticalAlignment="Top" HorizontalAlignment="Left"
Height
="20" Width="80"Click="textButton_Click" Margin="0,61,0,0"
/>

</Grid>

</UserControl>

 

定义了一个ClassB

public class
ClassB
: ViewModelBase

    {

 

        public ClassB()

        {

            MText = "";

        }

 

        public ClassB(String showText)

        {

            MText = showText;

        }

 

        private String _mText;

        public String MText

        {

            get

            {

                return _mText;

            }

            set

            {

                if (_mText !=
value
)

                {

                    _mText = value;

                    OnPropertyChanged("MText");

                }

            }

        }

}

 

再定义一个ClassA

    public classClassA :ViewModelBase

    {

        public ClassA()

        {

            MClassBs = new
ObservableCollection
<ClassB>();

            MClassBs.Add(new
ClassB
("MyName"));

            MClassBs.Add(new
ClassB
("HisName"));

        }

 

        public ObservableCollection<ClassB> MClassBs{get;set;}

    }

 

    对ClassADataBinding,注意注释部分Binding是错误的。因为你new 一个observableCollection <>后,mClass.MClassBs得到了新的地址,但是UI
一直记录的是原来的地址。所以新的地址并没有和UI产生DataBinding。

 

    public partialclassMainPage :UserControl

    {

        ClassA mClass;

        public MainPage()

        {

            InitializeComponent();

            mClass=new
ClassA
();

            LayoutRoot.DataContext = mClass;

        }

 

        private void textButton_Click(object sender,RoutedEventArgs e)

        {

           

            //mClass.MClassBs = new ObservableCollection<ClassB>();

            //mClass.MClassBs.Add(new ClassB("Hello"));

 

            mClass.MClassBs.Clear();

            mClass.MClassBs.Add(new
ClassB
("Hello"));

        }

    }

 

    如果要想注释的代码能work,必须给MClassBs赋值的时候,要发消息给UI知道。既然ObserverableCollection不发,我们自己发。修改ClassA如下:

namespace DataBindingReference
{
    public class ClassA : ViewModelBase
    {
        public ClassA()
        {
            MClassBs = new ObservableCollection<ClassB>();
            MClassBs.Add(new ClassB("MyName"));
            MClassBs.Add(new ClassB("HisName"));
        }

        private ObservableCollection<ClassB> mClassBs;
        public ObservableCollection<ClassB> MClassBs
        {
            get
            {
                return mClassBs;
            }
            set
            {
                if (mClassBs != value)
                {
                    mClassBs = value;
                    OnPropertyChanged("MClassBs");
                }
            }
        }
    }
}

 

 这样子再运行一次注释的代码就ok了。。

 

 

抱歉!评论已关闭.