首页 > 其他分享 >【转】WPF 中双向绑定通知机制之OBSERVABLECOLLECTION使用

【转】WPF 中双向绑定通知机制之OBSERVABLECOLLECTION使用

时间:2022-11-23 17:01:51浏览次数:52  
标签:OBSERVABLECOLLECTION Name Students 绑定 System using new WPF Id

WPF 中双向绑定通知机制之ObservableCollection使用

msdn中   ObservableCollection<T> 类    表示一个动态数据集合,在添加项、移除项或刷新整个列表时,此集合将提供通知。

在许多情况下,所使用的数据是对象的集合。 例如,数据绑定中的一个常见方案是使用 ItemsControl(如 ListBoxListView 或 TreeView)来显示记录的集合。

可以枚举实现 IEnumerable 接口的任何集合。 但是,若要设置动态绑定,以便集合中的插入或删除操作可以自动更新 UI,则该集合必须实现 INotifyCollectionChanged 接口。 此接口公开 CollectionChanged 事件,只要基础集合发生更改,都应该引发该事件。

WPF 提供 ObservableCollection<T> 类,它是实现 INotifyCollectionChanged 接口的数据集合的内置实现。

还有许多情况,我们所使用的数据只是单纯的字段或者属性,此时我们需要为这些字段或属性实现INotifyPropertyChanged接口,实现了该接口,只要字段或属性的发生了改变,就会提供通知机制。

ObservableCollection<T>实现

前台xmal

复制代码 复制代码
<Window x:Class="WpfApplication1.WindowObservable"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window8" Height="356" Width="471">
    <Grid>
        <StackPanel Height="295" HorizontalAlignment="Left" Margin="10,10,0,0" Name="stackPanel1" VerticalAlignment="Top" Width="427">
            <TextBlock Height="23" Name="textBlock1" Text="学员编号:" />
            <TextBox Height="23" Name="txtStudentId" Width="301" HorizontalAlignment="Left"/>
            <TextBlock Height="23" Name="textBlock2" Text="学员列表:" />
            <ListBox Height="156" Name="lbStudent" Width="305" HorizontalAlignment="Left">
                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <StackPanel Name="stackPanel2" Orientation="Horizontal">
                            <TextBlock  Text="{Binding Id,Mode=TwoWay}" Margin="5" Background="Beige"/>
                            <TextBlock Text="{Binding Name,Mode=TwoWay}" Margin="5"/>
                            <TextBlock  Text="{Binding Age,Mode=TwoWay}" Margin="5"/>
                        </StackPanel>
                    </DataTemplate>
                </ListBox.ItemTemplate>
            </ListBox>
            <Button Content="Button" Height="23" Name="button1" Width="75" HorizontalAlignment="Left" Click="button1_Click" />
        </StackPanel>
    </Grid>
</Window>
复制代码 复制代码

后台cs

复制代码 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace WpfApplication1
{
    public partial class WindowObservable : Window
    {
        ObservableCollection<Students> infos = new ObservableCollection<Students>() { 
            new Students(){ Id=1, Age=11, Name="Tom"},
            new Students(){ Id=2, Age=12, Name="Darren"},
            new Students(){ Id=3, Age=13, Name="Jacky"},
            new Students(){ Id=4, Age=14, Name="Andy"}
            };

        public WindowObservable()
        {
            InitializeComponent();

            this.lbStudent.ItemsSource = infos;

            this.txtStudentId.SetBinding(TextBox.TextProperty, new Binding("SelectedItem.Id") { Source = lbStudent });
        }
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            infos[1] = new Students() { Id = 4, Age = 14, Name = "这是一个集合改变" };
            infos[2].Name = "这是一个属性改变";
        }

        public class Students
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public int Age { get; set; }
        }    
    }
}
复制代码 复制代码

在这个例子中我们将Students数据对象用ObservableCollection<T>来修饰。这样当我们点击click的时候我们看到。当我们点击后只有student整个对象的改变引发了后台通知机制。

INotifyPropertyChanged实现

INotifyPropertyChanged会向客户端发出某一属性值已更改的通知。当元素属性值改变时,会通知后台model

前台代码不变,我们让后台Students  Model实现INotifyPropertyChanged接口。

复制代码 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace WpfApplication1
{
    public partial class WindowObservable : Window
    {
        ObservableCollection<Students> infos = new ObservableCollection<Students>() { 
            new Students(){ Id=1, Age=11, Name="Tom"},
            new Students(){ Id=2, Age=12, Name="Darren"},
            new Students(){ Id=3, Age=13, Name="Jacky"},
            new Students(){ Id=4, Age=14, Name="Andy"}
            };

        public WindowObservable()
        {
            InitializeComponent();

            this.lbStudent.ItemsSource = infos;

            this.txtStudentId.SetBinding(TextBox.TextProperty, new Binding("SelectedItem.Id") { Source = lbStudent });
        }
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            infos[1] = new Students() { Id = 4, Age = 14, Name = "这是一个集合改变" };
            infos[2].Name = "这是一个属性改变";
        }
        public class Students : INotifyPropertyChanged
        {
            string _name;
            public int Id { get; set; }
            public string Name
            {
                get { return _name; }
                set { _name = value; OnPropertyChanged("Name"); }
            }
            public int Age { get; set; }
            protected internal virtual void OnPropertyChanged(string propertyName)
            {
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
            public event PropertyChangedEventHandler PropertyChanged;
        }
    }
}
复制代码 复制代码

此时我们再 运行代码会发现

使用DataContext为页面对象设置上下文

不管是集合还是对象都发生了改变。至此。我们的整个后台通知就能完美监视任何对象变动。

但是现在还有一个问题。我们如果在点击事件里面给infos赋值一个新的集合数据。如下

复制代码 复制代码
private void button1_Click(object sender, RoutedEventArgs e)
 {
            infos[1] = new Students() { Id = 4, Age = 14, Name = "这是一个集合改变" };
            infos[2].Name = "这是一个属性改变";
       infos = new ObservableCollection<Students>() { 
            new Students(){ Id=1, Age=11, Name="这是改变后的集合"},
            new Students(){ Id=2, Age=12, Name="这是改变后的集合"},
            new Students(){ Id=3, Age=13, Name="这是改变后的集合"},
            new Students(){ Id=4, Age=14, Name="这是改变后的集合"}
            };
}
复制代码 复制代码

会发现数据并没有变更。这是为什么?我们明明实现了ObservableCollection<T>类型啊。这是因为infos这个集合的地址变更并没有实现通知机制。当我们new一个对象赋值给infos时候,infos的地址指向变更了。所以集合里面数据的变化,infos变更后的数据就参与绑定了。我们这时候可以通过DataContext实现数据数据项的变更通知。我们添加一个ViewModel类,实现INotifyPropertyChanged接口

复制代码 复制代码
 public class ViewModel : INotifyPropertyChanged
    {
        private ObservableCollection<Students> studentList;
        public ObservableCollection<Students> StudentList
        {
            get
            {
                return this.studentList;
            }
            set
            {
                if (this.studentList != value)
                {
                    this.studentList = value;
                    OnPropertyChanged("StudentList");
                }
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
复制代码 复制代码

windowsObservable类修改为如下

复制代码 复制代码
public partial class WindowObservable : Window
    {
        ViewModel viewModel = new ViewModel();
        public WindowObservable()
        {
            InitializeComponent();
            viewModel.StudentList = new ObservableCollection<Students>() { 
            new Students(){ Id=1, Age=11, Name="Tom"},
            new Students(){ Id=2, Age=12, Name="Darren"},
            new Students(){ Id=3, Age=13, Name="Jacky"},
            new Students(){ Id=4, Age=14, Name="Andy"}
            };
            this.lbStudent.DataContext = viewModel;
        }
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            viewModel.StudentList[1] = new Students() { Id = 4, Age = 14, Name = "这是一个集合改变" };
           
            viewModel.StudentList = new ObservableCollection<Students>() { 
            new Students(){ Id=19, Age=111, Name="这是变化后的几何"},
            new Students(){ Id=29, Age=121, Name="这是变化后的几何"},
            new Students(){ Id=39, Age=131, Name="这是变化后的几何"},
            new Students(){ Id=49, Age=141, Name="这是变化后的几何"}
            };
            viewModel.StudentList[2].Name = "这是一个属性改变";
        }
    }
复制代码 复制代码

我们给xaml listbox设置如下绑定

ItemsSource="{Binding StudentList, Mode=TwoWay}"

运行程序我们发现集合的改变也会被通知到前台。

 

      转自 https://www.cnblogs.com/santian/p/4366832.html

标签:OBSERVABLECOLLECTION,Name,Students,绑定,System,using,new,WPF,Id
From: https://www.cnblogs.com/castlewu/p/16918943.html

相关文章

  • Repeater嵌套绑定Repeater
    privatevoidRpTypeBind(){//GetQuestionTypeAndCount()返回一个datatablethis.rptypelist.DataSource=LiftQuestionCtr.GetQuestionTypeAndCount......
  • vite+vue3批量导入静态资源图片;动态绑定大量图片
    vite版本:vite3;vue版本:vue3打包上线后发现,动态绑定的图片皆失效。单图可用import导入解决,但是若有大量图片,一一导入则耗时耗力。vue2+webpack可用require解决批量导......
  • 聊聊Spring中的数据绑定DataBinder
    数据绑定 这个概念在任何一个成型的框架中都是特别重要的(尤其是web框架),它能让框架更多的自动化,更好容错性以及更高的编码效率。它提供的能力是:把字符串形式的参数转换成服......
  • wpf 子页面调用父窗口方法
     参考:http://www.360doc.com/content/17/1113/11/24811_703389993.shtml//1)子页面后台定义委托(namespace下class外)//定义委托internaldelegatevoidColorChange(o......
  • wpf 后台添加控件
    音乐播放列表,鼠标右键点击列表时,出现添加到歌单,做成每次右键点击时,后台新增选项了(也可以前台绑定数据源每次增删改后更新数据源)TextBlocktext=newTextBlock();text.......
  • wpf 后台修改控件颜色(颜色Brush类型新建)
    16进制、rgb格式、提供的颜色示例:xxx.Foreground=newSolidColorBrush((Color)ColorConverter.ConvertFromString("#FFFFFF"));xxx.Background=newSolidColorBrus......
  • WPF-简单数据绑定
    为了保持数据和控件内容的同步,我们通常的方法是在:数据类中创建事件,在属性修改时通知控件修改内容;在控件所属类中创建事件,在内容修改时通知数据对象更新属性,这叫做数据绑定......
  • 在WPF中利用XPS文档实现打印功能
    摘要WPF重新规划了打印模型,将所有编码围绕System.Windows.Controls.PrintDialog,使用PrintDialog类可显示Print对话框、设置打印机首选项等等,并且可将元素、文档以及低级的......
  • Winform控件绑定数据
    目录简介绑定基类功能扩展简单控件绑定列表控件绑定绑定BindingList集合绑定DataTable表格绑定BindingSource源表格控件绑定绑定DataTable绑定BindingListUI线程全局类简......
  • C# WPF ListBox 最后追加项自动滚动到最后一项 ScrollIntoView
    用这个:lstbDynamicNote.ScrollIntoView(lstbDynamicNote.Items[lstbDynamicNote.Items.Count-1]);privatevoidDynamicNoteShow(stringdynamicNote){if(lstb......