【发布时间】:2017-07-28 20:41:35
【问题描述】:
我正在 Visual Studio 2017 中使用 C# 4.5.2 开发 WPF 应用程序。在应用程序中,我有一个自定义对象,该对象被滚动到 ObservableCollection<T> 中以供以后处理。如果/必要时,我希望能够处理这个CollectionChanged 事件。
我为类 (: INotifyPropertyChanged) 添加了适当的装饰,添加了事件和处理程序,并使用接口 PropertyChanged 为我的对象中的每个属性分配了属性:
public class OrderLineItem : INotifyPropertyChanged
{
private int _lineItemNumber;
public int LineItemNumber
{
get => _lineItemNumber;
set { _lineItemNumber = value; OnPropertyChanged(); }
}
private int _quantity;
public int Quantity
{
get => _quantity;
set { _quantity = value; OnPropertyChanged(); }
}
private string _partNumber;
public string PartNumber
{
get => _partNumber;
set { _partNumber = value; OnPropertyChanged(); }
}
private Hinge _hinged;
public Hinge Hinging
{
get => _hinged;
set { _hinged = value; OnPropertyChanged(); }
}
private Finish _finished;
public Finish Finished
{
get => _finished;
set { _finished = value; OnPropertyChanged(); }
}
private decimal _unitPrice;
public decimal UnitPrice
{
get => _unitPrice;
set { _unitPrice = value; OnPropertyChanged(); }
}
private decimal _modifyPrice;
public decimal ModifyPrice
{
get => _modifyPrice;
set { _modifyPrice = value; OnPropertyChanged(); }
}
private decimal _extendedPrice;
public decimal ExtendedPrice
{
get => _extendedPrice;
set { _extendedPrice = value; OnPropertyChanged(); }
}
private List<string> _modifications;
public List<string> Modifications
{
get => _modifications;
set { _modifications = value; OnPropertyChanged(); }
}
private CabinetType _type;
public CabinetType Type
{
get => _type;
set { _type = value; OnPropertyChanged(); }
}
private string _display;
public string Display
{
get => _display;
set { _display = value; OnPropertyChanged(); }
}
public enum Hinge { None = 0, L, R, BD }
public enum Finish { None = 0, L, R, B }
public OrderLineItem()
{
LineItemNumber = -1;
Quantity = -1;
PartNumber = string.Empty;
Hinging = Hinge.None;
Finished = Finish.None;
UnitPrice = 0.00m;
ModifyPrice = 0.00m;
ExtendedPrice = 0.00m;
Modifications = new List<string>();
Type = CabinetType.None;
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
在我的MainWindow.xaml.cs 文件中,我将.CollectionChanged 处理程序添加到我的ObservableCollection<T> 和.PropertyChanged 处理程序到我的对象:
private void AddedItemsOnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach (OrderLineItem newItem in e.NewItems)
{
_addedItems.Add(newItem);
newItem.PropertyChanged += OnItemPropertyChanged;
}
}
if (e.OldItems != null)
{
foreach (OrderLineItem oldItem in e.OldItems)
{
_addedItems.Add(oldItem);
oldItem.PropertyChanged -= OnItemPropertyChanged;
}
}
}
private void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e)
{
OrderLineItem item = sender as OrderLineItem;
if (item != null) _addedItems.Add(item);
}
每当我将一个项目添加到集合中时,我都会向它添加 PropertyChanged 处理程序:
...
item.PropertyChanged += ItemOnPropertyChanged;
...
此集合通过 .ItemsSource 属性显示在 DataGrid 中。
此问题标题中的问题仅发生在 实施 INotifyPropertyChanged 及其相关方法/接口等之后。
我能够获得的堆栈跟踪没有为我提供任何有用的信息(行号、文件、方法等)来尝试调试它。我确实启用了所有调试选项,以确保我没有忽略任何潜在的异常。 Here is a pastebin of the exception。指示的行号是这样的:
AppDomain.CurrentDomain.UnhandledException +=
(sender, args) => throw new Exception("Unhandled exception: " + args.ExceptionObject);
如果我没有这行,或者注释掉this is a pastebin of the exception I get instead。
除了不实现CollectionChanged事件之外,我应该如何继续尝试解决这个问题?
【问题讨论】:
-
只是一件小事——你的代码有
newItem.PropertyChanged += OnItemPropertyChanged;,但事件处理程序通常没有名称中的On部分——约定是以On开头的方法是在那里引发事件,而不是处理它们。 -
@Enigmativity 很好,我相信 ReSharper 可能已经自动命名了该方法。
-
您能否发布您的 DataGrid 的 XAML 源代码?我在类似情况下遇到了同样的异常,通过显式设置绑定的 Path 属性(例如,将 Binding="{Binding (a:B.C)}" 更改为 Binding="{Binding Path=(a:B.C)} ”)。我不确定为什么会这样。
-
@Enigmativity,当事件处理程序以“On”开头命名时,文档中有很多示例。就个人而言,为了避免混淆,我尽量遵守规则:名称处理程序以“On”开头,创建事件的方法以“Raise”开头。我为代表使用结尾的“处理程序”。
-
@EldHasp - 你说得对,很多人错误地执行了约定。
标签: c# wpf observablelist