Count
के संबंध में, आपको यह बिल्कुल करने की ज़रूरत नहीं है। बस Tasks.Count
से बांधें और आपकी बाइंडिंग ObservableCollection
द्वारा परिवर्तन की अधिसूचना प्राप्त की जाएगी।
Completed
एक अलग कहानी है, क्योंकि यह ObservableCollection
के बाहर है। फिर भी, अमूर्त/इंटरफ़ेस के स्तर से, आप को Tasks
संग्रह की संपत्ति होने के लिए वास्तव में चाहते हैं।
इस के लिए, मुझे लगता है कि एक बेहतर दृष्टिकोण अपने Tasks
संपत्ति के लिए "उप" व्यू-मॉडल बनाने के लिए होगा:
public class TasksViewModel : ObservableCollection<Task>
{
public int Completed
{
get { return this.Count(t => t.IsComplete); }
}
protected override void OnPropertyChanged(PropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if(e.PropertyName == "Count") NotifyCompletedChanged();
}
protected override void OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
base.OnCollectionChanged(e);
NotifyCompletedChanged();
}
void NotifyCompletedChanged()
{
OnPropertyChanged(_completedChangedArgs);
}
readonly PropertyChangedEventArgs _completedChangedArgs = new PropertyChangedEventArgs("Completed");
}
यह आपको ObservableCollection
की सभी सुविधाओं देता है, और प्रभावी ढंग से Completed
बनाता है इसका संपत्ति हिस्सा। हमने अभी भी उन मामलों पर कब्जा नहीं किया है जहां पूर्ण वस्तुओं की संख्या वास्तव में बदलती है, लेकिन हमने कुछ हद तक अनावश्यक अधिसूचनाओं की संख्या कम कर दी है।
अब viewmodel सिर्फ संपत्ति है:
public TasksViewModel Tasks { get; set; }
... और आप Tasks
, Tasks.Count
, और आसानी से Tasks.Completed
करने के लिए बाध्य कर सकते हैं।
एक विकल्प के रूप से, अगर आप "मुख्य" व्यू-मॉडल पर इन अन्य गुण पैदा होता है, यदि आप एक subclassed ObservableCollection<T>
की इस धारणा को कुछ पद्धति जहां आप एक Action<string>
में पारित कर सकते हैं के साथ एक बनाने के लिए ले जा सकते हैं प्रतिनिधि, जो मुख्य दृश्य-मॉडल पर संपत्ति परिवर्तन अधिसूचना बढ़ाने और संपत्ति के नामों की कुछ सूची का प्रतिनिधित्व करेगा। इस संग्रह में तो प्रभावी ढंग से दृश्य-मॉडल पर संपत्ति परिवर्तन सूचनाएं बढ़ा सकता है:
public class ObservableCollectionWithSubscribers<T> : ObservableCollection<T>
{
Action<string> _notificationAction = s => { }; // do nothing, by default
readonly IList<string> _subscribedProperties = new List<string>();
public void SubscribeToChanges(Action<string> notificationAction, params string[] properties)
{
_notificationAction = notificationAction;
foreach (var property in properties)
_subscribedProperties.Add(property);
}
protected override void OnPropertyChanged(PropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
NotifySubscribers();
}
protected override void OnCollectionChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
base.OnCollectionChanged(e);
NotifySubscribers();
}
void NotifySubscribers()
{
foreach (var property in _subscribedProperties)
_notificationAction(property);
}
}
तुम भी ObservableCollection<Task>
के रूप में संपत्ति प्रकार छोड़ सकते हैं।
public class ViewModel : INotifyPropertyChanged
{
public ViewModel()
{
var tasks = new ObservableCollectionWithSubscribers<Task>();
tasks.SubscribeToChanges(Notify, "Completed");
Tasks = tasks;
}
public ObservableCollection<Task> Tasks { get; private set; }
public int Completed
{
get { return Tasks.Count(t => t.IsComplete); }
}
public event PropertyChangedEventHandler PropertyChanged;
void Notify(string property)
{
var handler = PropertyChanged;
if(handler != null) handler(this, new PropertyChangedEventArgs(property));
}
}
यह निश्चित रूप से एक बेहतर डिजाइन है। –