代码之家  ›  专栏  ›  技术社区  ›  Aleksey Pavlov

ObservableCollection删除/添加方法不起作用,即使列表中的项

  •  1
  • Aleksey Pavlov  · 技术社区  · 6 年前

    我对添加和删除收藏中的项目有点问题。

        private ObservableCollection<PrintDocumentSettingsModel> _AllPrintingFormats;
        public ObservableCollection<PrintDocumentSettingsModel> PrintingFormats
        {
            get
            {
                var formats = new ObservableCollection<PrintDocumentSettingsModel>(
                    _AllPrintingFormats.Where(x => x.IsStandartPrinter == IsStandartPrinter));
                if (!formats.Contains(SelectedFormat))
                    SelectedFormat = formats.FirstOrDefault();
                return formats;
            }
            set { _AllPrintingFormats = value; OnPropertyChanged("PrintingFormats"); }
        }
    
        private bool _IsStandartPrinter;
        public bool IsStandartPrinter
        {
            get { return _IsStandartPrinter; }
            set
            {
                _IsStandartPrinter = value;
                OnPropertyChanged("IsStandartPrinter");
                OnPropertyChanged("PrintingFormats");
            }
        }
    
        private void DeleteFormat()
        {
            if (SelectedFormat != null && SelectedFormat.IsEditable &&
                PrintingFormats.Contains(SelectedFormat))
            {
                PrintingFormats.Remove(SelectedFormat);
                OnPropertyChanged("PrintingFormats");
            }
        }
    

    方法 删除窗体() 即使if语句返回true也不起作用。但如果我重写 删除窗体() 通过替换 打印格式 具有 _所有打印格式 该方法工作正常。

        private void DeleteFormat()
        {
            if (SelectedFormat != null && SelectedFormat.IsEditable &&
                _AllPrintingFormats.Contains(SelectedFormat))
            {
                _AllPrintingFormats.Remove(SelectedFormat);
                OnPropertyChanged("PrintingFormats");
            }
        }
    

    那么诀窍是什么呢?

    1 回复  |  直到 6 年前
        1
  •  2
  •   Everyone    6 年前

    这不是写属性的好方法。属性应返回类中的私有对象(无论是显式声明还是隐式声明),除非在某些情况下该属性与任何实际私有成员无关。

    当你写这个的时候:

        get
        {
            var formats = new ObservableCollection<PrintDocumentSettingsModel>(
                _AllPrintingFormats.Where(x => x.IsStandartPrinter == IsStandartPrinter));
            if (!formats.Contains(SelectedFormat))
                SelectedFormat = formats.FirstOrDefault();
            return formats;
        }
        set { _AllPrintingFormats = value; OnPropertyChanged("PrintingFormats"); }
    

    您正在创建一个名为 formats 并返回对该对象的引用。这与实际的私人成员无关 _AllPrintingFormats .因此,当你打电话的时候 PrintingFormats.Remove(SelectedFormat); 它将在上尝试操作 格式 get 功能 PrintingFormats . 这一变化没有反映在 _所有打印格式 因为它是在另一个对象上执行的。

    此外,更改是完全无用的,因为您不会持有任何引用 格式 以后会被垃圾收集。您所拥有的代码在性能(在 得到 每次调用属性,并使用LINQ创建变量)和on space(即使在引用on之后 格式 释放后,它将不会被GC直接清除,这意味着您将拥有多个 格式 僵尸等待收集并占用空间)。

    顺便说一下,在一个集合上使用LINQ是一个不太好的主意,因为它很可能被多个线程访问,因为您可以有竞争条件。你必须明白这句话:

    var formats = new ObservableCollection<PrintDocumentSettingsModel>(
            _AllPrintingFormats.Where(x => x.IsStandartPrinter == IsStandartPrinter));
    

    不会马上决定。也就是说,您将无法在此调用中获得符合LINQ条件的元素。这将得到解决 之后 你回来 格式 这意味着由另一个线程所做的任何更改将在该行和实际使用之间产生不同的结果。 格式

    如果你想维护财产并保持原样,你总是可以做你在问题的第二部分所做的,并且直接使用 _所有打印格式 . 但是,我建议您更改 打印格式 进入:

    get { return _AllPrintingFormats }
    set 
    { 
        _AllPrintingFormats = value; 
        OnPropertyChanged("PrintingFormats"); 
    }
    

    如果您真的需要LINQ查询,可以在 打印格式 而不是由物业来完成。