我在添加和删除集合中的项目时遇到了一个小问题。
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");
}
}
方法 DeleteFormat()不起作用,即使if语句返回true。但是,如果我将 PrintingFormats 替换为 _AllPrintingFormats 来重写 DeleteFormat(),则该方法将正常工作。
private void DeleteFormat()
{
if (SelectedFormat != null && SelectedFormat.IsEditable &&
_AllPrintingFormats.Contains(SelectedFormat))
{
_AllPrintingFormats.Remove(SelectedFormat);
OnPropertyChanged("PrintingFormats");
}
}
那有什么窍门?
答案 0 :(得分:2)
这不是编写属性的好方法。一个属性应该在您的类中返回一个私有对象(无论是显式还是隐式声明),但在某些情况下,该属性与任何实际的私有成员无关。
当您写这篇文章时:
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);
时,它将尝试在formats
的{{1}}函数中声明并实例化的get
上进行操作。由于此更改是在其他对象上执行的,因此不会反映在PrintingFormats
上。
此外,该更改完全无用,因为您将不会保留对_AllPrintingFormats
的任何引用,并且稍后将对其进行垃圾回收。您拥有的代码在性能(每次调用该属性时在formats
中创建一个新变量,以及使用LINQ创建变量)和空间(即使在get
上的引用之后)都效率低下被释放,它将不会被GC直接清除,这意味着您将有多个formats
僵尸对象等待收集并占用空间。
顺便说一句,在一个很可能被多个线程访问的集合上使用LINQ并不是一个好主意,因为您可能会遇到竞争条件。您必须了解这一行:
formats
将不会立即确定。也就是说,此调用不会获得满足LINQ标准的元素。您返回var formats = new ObservableCollection<PrintDocumentSettingsModel>(
_AllPrintingFormats.Where(x => x.IsStandartPrinter == IsStandartPrinter));
后,将在 上解决此问题,这意味着另一个线程所做的任何更改将在行和实际使用{{1}之间产生不同的结果。 }
如果您想维护该属性并将其保持不变,则始终可以执行问题第二部分中的操作,然后直接使用formats
。但是,我建议将formats
更改为:
_AllPrintingFormats
如果确实需要LINQ查询,则可以在PrintingFormats
上执行此查询,而不是由属性来完成。