Đây là trả lời một bình luận tôi rời . Hy vọng điều này sẽ trả lời câu hỏi của bạn, Shimmy. Chỉ cần bình luận và tôi sẽ rút ngắn hoặc xóa nó nếu nó không trả lời câu hỏi của bạn.
Bạn sẽ cần cả hai giao diện INotifyPropertyChanging và INotifyPropertyChanged sẽ được triển khai trên lớp của bạn (trừ khi nó giống như đối tượng khung thực thể, mà tôi tin rằng thực hiện các nội bộ này).
Và trước khi bạn đặt giá trị cho thuộc tính này, bạn sẽ cần tăng sự kiện NotifyPropertyChanging.PropertyChanging, sử dụng tên thuộc tính trong hàm tạo PropertyChangingEventArgs.
Và sau khi bạn đặt giá trị này, bạn cần phải nâng cao sự kiện NofityPropertyChanged.PropertyChanged, một lần nữa bằng cách sử dụng tên của thuộc tính này đang được nâng lên trong constructor PropertyChangedEventArgs.
Sau đó, bạn phải xử lý các sự kiện PropertyChanging và PropertyChanged. Trong sự kiện PropertyChanging, bạn cần phải cache giá trị. Trong sự kiện PropertyChanged, bạn có thể so sánh và ném một ngoại lệ.
Để nhận thuộc tính từ PropertyChanging/PropertyChanged event args, bạn cần phải sử dụng sự phản hồi.
// PropertyName is the key, and the PropertyValue is the value.
Dictionary <string, object> propertyDict = new Dictionary<object, object>();
// Convert this function prototype to C# from VBNet. I like how Handles is descriptive.
Public Sub PropertyChanging(sender As object, e As PropertyChangingEventArgs) Handles Foo.PropertyChanging
{
if (sender == null || preventRecursion)
{
return;
} // End if
Type senderType = sender.GetType();
PropertyInfo info = senderType.GetProperty(e.PropertyName);
object propertyValue = info.GetValue(sender, null);
// Change this so it checks if e.PropertyName already exists.
propertyDict.Add(e.PropertyName, propertyValue);
} // End PropertyChanging() Event
// Convert this function prototype to C# from VBNet. I like how Handles is descriptive.
Public Sub PropertyChanged(sender As object, e As PropertyChangedEventArgs) Handles Foo.PropertyChanged
{
if (sender == null || preventRecursion)
{
return;
} // End if
Type senderType = sender.GetType();
PropertyInfo info = senderType.GetProperty(e.PropertyName);
object propertyValue = info.GetValue(sender, null);
// Change this so it makes sure e.PropertyName exists.
object oldValue = propertyDict(e.PropertyName);
object newValue = propertyValue;
// No longer needed.
propertyDict.Remove(e.PropertyName);
if (/* some condition */)
{
try {
preventRecursion = true;
info.SetValue(oldValue, null);
Throw New Exception();
} finally {
preventRecursion = false;
} // End try
} // End if
} // End PropertyChanging() Event
Lưu ý cách tôi đang sử dụng PreventRecursion, một boolean tôi quên thêm ở trên các phương pháp này là gì? Khi bạn đặt lại thuộc tính về giá trị trước đó của nó, các sự kiện này sẽ bị thu hồi.
tl; dr
Bây giờ bạn có thể lấy được một sự kiện duy nhất mà kế thừa từ INotifyPropertyChanged, nhưng sử dụng một cuộc tranh cãi mà giữ một đối tượng đại diện cho các giá trị trước đó cũng như Tên thuộc tính.Và điều đó sẽ làm giảm số lượng sự kiện bị sa thải xuống một, có chức năng tương tự và có khả năng tương thích ngược với INotifyPropertyChanged. Nhưng nếu bạn muốn xử lý bất cứ điều gì trước khi bất động sản được thiết lập (nói thuộc tính có thay đổi không thể đảo ngược hoặc bạn cần phải thiết lập các thuộc tính khác trước khi thiết lập biến đó, nếu không ngoại lệ sẽ bị ném), bạn sẽ không thể làm việc đó đi.
Nhìn chung, phương pháp này là một cách rất cũ để làm việc. Tôi sẽ nhận câu trả lời của Poker Villian và có thể nhập dữ liệu không hợp lệ. Nhưng không cho phép lưu vào cơ sở dữ liệu.
Khuôn khổ thực thể có một số mã tuyệt vời để xác thực. Bạn thêm xác thực vào các thuộc tính của bạn thông qua các thuộc tính. Và sau đó nó sẽ chăm sóc công việc xử lý các thuộc tính đó. Sau đó, bạn có thể tạo một thuộc tính được gọi là IsValid, gọi là xác nhận hợp lệ khung thực thể Entity Framework. Nó cũng phân biệt cả hai lỗi trường (như nhập sai ký tự hoặc có chuỗi quá dài) và lỗi lớp (như thiếu dữ liệu hoặc khóa xung đột).
Sau đó, bạn có thể liên kết IsValid để kiểm soát xác thực và chúng sẽ hiển thị bong bóng màu đỏ khi dữ liệu không hợp lệ được nhập. Hoặc bạn chỉ có thể thực hiện xác thực IsValid. Nhưng nếu IsValid là sai, sự kiện SaveChanges sẽ cần phải hủy lưu.
btw. Mã được cung cấp sẽ không biên dịch và chỉ là mã giả (trộn vb và C#). Nhưng tôi tin rằng nó mô tả nhiều hơn C# một mình - cho thấy chính xác những gì đang được xử lý.
PropertyChangingEventArgs không có liên quan đến CancelEventArgs. Họ có thời gian họ cần phải được sử dụng riêng cho các mục đích khác nhau. Để buộc thừa kế sẽ gây ra biến chứng không cần thiết và thất vọng (kết nối chặt chẽ chúng với nhau). Có PropertyChangingEvent và PropertyChangedEvent, và tôi tin rằng chúng thỏa mãn các chức năng mà bạn mong muốn mà không cần thay đổi đối với chúng (chưa kể, điều đó sẽ phá vỡ .NET 1.1 thành .NET 4.0 tương thích). – TamusJRoyce
@TamusJRoyce, OK, tôi đồng ý, không nên kế thừa từ 'CancelEventArgs', nhưng điều tôi cần làm là yêu cầu khác của tôi, cung cấp giá trị ứng cử viên (cách dễ dàng để lấy nó là nhận các thuộc tính phương thức hiện tại lượng chi phí hiệu suất). – Shimmy