红着眼 2023-11-27 10:03 采纳率: 27.8%
浏览 22
已结题

WPF CollectionChanged更新绑定的问题

为了能更好的得到帮助,我将问题代码都分离出以下的这种形式。别问我为啥这样做,业务需求啦。
页面A绑定的全部学生信息,以列表的形式展示,可以进行增删改查。
页面B绑定的是前N名次的学生信息,以自定义DataGrid展示。
页面A操作数据后,页面B会立刻通知更新。

问题
一,QueryAllBtn_Click方法中查询前50名学生信息的代码Cache.OcAList集合数据变更了,为什么页面没有变更的呢?
不是在初始化中this.AllUserGrid.ItemsSource = Cache.OcAList;这样进行绑定了吗?
每一次查询都需要绑定?可是DeleteUserBtn_Click删除数据页面又会更新。

二,CollectionChanged都重新赋值了,为什么不会进DisplayViewModel这个类的UpdateDisplayList这个方法呢?CollectionChanged重新赋值会触发什么事件呢?

全部代码如下
一:学生信息类

using System;
using System.Linq;
using SG.Views.Base.Model;
using System.Collections.Generic;

namespace SG.com.ll.Config
{
    public class User : ViewModelBase
    {
        public string ID { get; set; }//ID不可修改
        public string Name { get; set; }//姓名不可修改
        private int score;//成绩可以修改

        public int Score
        {
            get { return score; }
            set
            {
                if (score == value) return;
                score = value; this.OnPropertyChanged("Score");
            }
        }
    }
}

二:数据缓存类

using System;
using System.Linq;
using System.ComponentModel;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace SG.com.ll.Config
{
    /// <summary>
    /// 测试类
    /// </summary>
    public class Cache
    {
        //第一个集合,计划展示全部数据
        private static ObservableCollection<User> ocAList = new ObservableCollection<User>();
        //第二个集合,计划展示前3名的数据
        private static ObservableCollection<User> ocBList = new ObservableCollection<User>();

        public static ObservableCollection<User> OcAList
        {
            get { return Cache.ocAList; }
            set { Cache.ocAList = value; }
        }
        public static ObservableCollection<User> OcBList
        {
            get { return Cache.ocBList; }
            set
            {
                Cache.ocBList = value;
                Console.WriteLine("集合2中的数据条数是:" + Cache.ocBList.Count);
                for (int i = 0; i < Cache.ocBList.Count; i++)
                {
                    string a = Cache.ocBList[i].Name;
                    Console.WriteLine(a);
                }
                OnStaticPropertyChanged("OcBList");
            }
        }

        public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged;
        private static void OnStaticPropertyChanged(string propertyName = null)
        {
            if (propertyName.StartsWith("get_") || propertyName.StartsWith("set_"))
            {
                propertyName = propertyName.Substring("get_".Length);
            }
            OnStaticPropertyChanged(new PropertyChangedEventArgs(propertyName));
        }
        private static void OnStaticPropertyChanged(PropertyChangedEventArgs e)
        {
            if (StaticPropertyChanged == null) return;
            StaticPropertyChanged.Invoke(null, e);
        }
    }
}

三:数据模型类

using System;
using System.Linq;
using SG.com.ll.Config;
using SG.Views.Base.Model;
using SG.com.ll.Config.Notice;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;

namespace SG.Views.Main
{
    public class DisplayViewModel : ViewModelBase
    {
        /// <summary>
        /// 首页数据模型
        /// </summary>
        /// <param name="n"></param>
        public DisplayViewModel(int n)
        {
            UpdateDisplayList(null, n);
            Cache.OcAList.CollectionChanged += (s, e) => UpdateDisplayList(e, n);
        }
        /// <summary>
        /// 首页数据筛选方法
        /// </summary>
        /// <param name="n"></param>
        private void UpdateDisplayList(NotifyCollectionChangedEventArgs e, int n)
        {
            Console.WriteLine("------------------------------------");
            if (e != null)
            {
                if (e.Action == NotifyCollectionChangedAction.Add)
                {
                    Console.WriteLine("添加被触发");
                }
                else if (e.Action == NotifyCollectionChangedAction.Remove)
                {
                    Console.WriteLine("删除被触发");
                }
                else if (e.Action == NotifyCollectionChangedAction.Replace)
                {
                    Console.WriteLine("替换被触发");
                }
            }
            else
            {
                Console.WriteLine("初始化触发");
                Cache.OcBList = new ObservableCollection<User>(Cache.OcAList.Take(n));
            }
        }
    }
}

四:页面A代码

/// <summary>
/// 初始化
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Window_Loaded(object sender, RoutedEventArgs e)
{
    //得到1000个学生信息
    Cache.OcAList = myDB.GetUser(1000);
    //进行绑定
    this.AllUserGrid.ItemsSource = Cache.OcAList;
}

/// <summary>
/// 只查询50个学生信息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void QueryAllBtn_Click(object sender, RoutedEventArgs e)
{
    Cache.OcAList = myDB.GetUser(50);
}

/// <summary>
/// 修改选中学生的成绩
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void UpdateUserBtn_Click(object sender, RoutedEventArgs e)
{
    User user = this.AllUserGrid.SelectedItem as User;
    user.Score = 100;
}

/// <summary>
/// 删除学生
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void DeleteUserBtn_Click(object sender, RoutedEventArgs e)
{
    int index = this.AllUserGrid.SelectedIndex;
    Cache.OcAList.RemoveAt(index);
}

五:B页面代码

/// <summary>
/// 初始化
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void Window_Loaded(object sender, RoutedEventArgs e)
{
    //数据模型初始化
    new DisplayViewModel(3);
    //进行绑定
    this.TOPUserScoreGrid.ItemsSource = Cache.OcBList;
}
  • 写回答

16条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2023-11-27 10:04
    关注
    获得0.45元问题酬金

    引自强大而免费的微信小程序:皆我百晓生

    问题一:
    在QueryAllBtn_Click方法中,虽然更新了Cache.OcAList的数据,但是页面中绑定的ItemsSource并没有重新赋值,所以页面没有变化。

    解决办法:
    在QueryAllBtn_Click方法中,更新完Cache.OcAList的数据后,需要重新给AllUserGrid.ItemsSource赋值,使页面重新绑定数据。

    修改后的代码如下:

    private void QueryAllBtn_Click(object sender, RoutedEventArgs e)
    {
        Cache.OcAList = myDB.GetUser(50);
        this.AllUserGrid.ItemsSource = Cache.OcAList;
    }
    

    问题二:
    CollectionChanged重新赋值不会触发DisplayViewModel类的UpdateDisplayList方法是因为在Cache类中的OcBList的set方法中,并没有重新赋值,只是触发了StaticPropertyChanged事件。

    解决办法:
    在Cache类中的OcBList的set方法中,重新赋值后需要触发StaticPropertyChanged事件,并传入"OcBList"作为参数。

    修改后的代码如下:

    public static ObservableCollection<User> OcBList
    {
        get { return Cache.ocBList; }
        set
        {
            Cache.ocBList = value;
            Console.WriteLine("集合2中的数据条数是:" + Cache.ocBList.Count);
            for (int i = 0; i < Cache.ocBList.Count; i++)
            {
                string a = Cache.ocBList[i].Name;
                Console.WriteLine(a);
            }
            OnStaticPropertyChanged("OcBList");
            OnStaticPropertyChanged("OcBList");
        }
    }
    
    评论 编辑记录

报告相同问题?

问题事件

  • 系统已结题 12月5日
  • 修改了问题 11月27日
  • 创建了问题 11月27日

悬赏问题

  • ¥50 AI大模型精调(百度千帆、飞浆)
  • ¥15 关于#c语言#的问题:我在vscode和codeblocks中编写c语言时出现打不开源文件该怎么办
  • ¥15 非科班怎么跑代码?如何导数据和调参
  • ¥15 福州市的全人群死因监测点死亡原因报表
  • ¥15 Altair EDEM中生成一个颗粒,并且各个方向没有初始速度
  • ¥15 系统2008r2 装机配置推荐一下
  • ¥500 服务器搭建cisco AnyConnect vpn
  • ¥15 悬赏Python-playwright部署在centos7上
  • ¥15 psoc creator软件有没有人能远程安装啊
  • ¥15 快速扫描算法求解Eikonal方程咨询