简体   繁体   中英

Access ObservableCollection items from property set

Given the following class used as a WPF DataContext:

class ViewModel
{
    public ObservableCollection<Task> Tasks { get; set; }
}

and this Task class:

public class Task
{
    private string startTime;

    public Task ID { get; set; }
    public string StartTime
    {
        get { return startTime; }
        set
        {
            // Access ObservableCollection items
            startTime = value;
            OnPropertyChanged("StartTime");
        }
    }
}

how can I, at the place in the code where you see "// Access ObservableCollection items", access the other items in the Tasks ObservableCollection so I can compare the StartTime of the instance being set to the StartTime of the other Task items in the Tasks ObservableCollection?

You have two options:

  1. You can inject ViewModel into Task

     public class Task { private ViewModel viewModel; public class Task(ViewModel viewModel) { this.viewModel = viewModel; } ... } 

    However, this makes Task class usable only with ViewModel class, because they are loosely coupled.

  2. you can perfom the StartTime validation in ViewModel. To do so you need to catch PropertyChanged events of all tasks.

    I created ExtendedObservableCollection that fires an event when property of any item changes:

     public class ExtendedObservableCollection<T> : ObservableCollection<T> where T : INotifyPropertyChanged { public event PropertyChangedEventHandler ItemPropertyChanged; protected override void ClearItems() { foreach (var item in Items) item.PropertyChanged -= OnItemPropertyChanged; base.ClearItems(); } protected override void InsertItem(int index, T item) { item.PropertyChanged += OnItemPropertyChanged; base.InsertItem(index, item); } protected override void RemoveItem(int index) { this[index].PropertyChanged -= OnItemPropertyChanged; base.RemoveItem(index); } protected override void SetItem(int index, T item) { this[index].PropertyChanged -= OnItemPropertyChanged; item.PropertyChanged += OnItemPropertyChanged; base.SetItem(index, item); } protected virtual void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e) { var handler = ItemPropertyChanged; if (handler != null) handler(sender, e); } } 

    and finaly the validation or what whatever you need

     public class ViewModel { public ExtendedObservableCollection<Task> Tasks { get; set; } public ViewModel() { Tasks=new ExtendedObservableCollection<Task>(); Tasks.ItemPropertyChanged += TaskPropertyChanged; } private void TaskPropertyChanged(object sender, PropertyChangedEventArgs e) { var changedTask = (Task)sender; if (e.PropertyName == "StartTime") { if (!IsStartTimeGreatedThenPrevious(changedTask )) changedTask.SetError("StartTime", "Start time has to be greated than in previous task) } } } 

you can add or remove items from Task collection and the ExtendedObservableCollection takes care of attaching/detaching to PropertyChanged event.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM