K
K
krslnkv2019-03-04 18:19:07
.NET
krslnkv, 2019-03-04 18:19:07

What is the correct way to implement PropertyChanged for two collections?

I have an ObservableCollection that is created from a model and will be used in multiple places, so I've separated it into a separate class. In the same place there is a collection filling. The second collection is created by assigning the first. Therefore, when I change something, I must notify the users of the collection about the change.
First collection:

class RoomsViewModel : INotifyPropertyChanged
{
    TechDContext dc = new TechDContext();
    public RoomsViewModel()
    {
        FillRooms();
    }

    public void FillRooms()
    {
        rooms = new ObservableCollection<RoomViewModel>(dc.Rooms.Select(r => new RoomViewModel
        {
            Room_id = r.Room_id,
            Room_no = r.Room_no,
            Floor = r.Floor
        }));
        OnPropertyChanged(nameof(rooms));
    }

    private ObservableCollection<RoomViewModel> rooms;
    public ObservableCollection<RoomViewModel> Rooms
    {
        get
        {
            return rooms;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged([CallerMemberName]string prop = "")
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(prop));
    }
}

Second collection and method for adding a new entry
class RoomsPageViewModel : INotifyPropertyChanged
{
    TechDContext dc = new TechDContext();
    RoomsViewModel roomsViewModel = new RoomsViewModel();

    public RoomsPageViewModel()
    {
        FillRoomsPage();
    }

    private void FillRoomsPage()
    {
        RoomsPage = roomsViewModel.Rooms;
        OnPropertyChanged(nameof(RoomsPage));
    }

    private ObservableCollection<RoomViewModel> roomsPage;
    public ObservableCollection<RoomViewModel> RoomsPage
    {
        get
        {
            return roomsPage;
        }
        set
        {
            roomsPage = value;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged([CallerMemberName]string prop = "")
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(prop));
    }

    public void AddRoom(string no, string fl)
    {
        string roomNo = (String)no;
        string floor = (String)fl;
        if (roomNo.Trim()!=""&&floor.Trim()!="")
        {
            bool query = dc.Rooms.Any(r => r.Room_no == roomNo);
            if (query == true)
            {
                MessageBoxResult message = MessageBox.Show($"Номер {roomNo} уже занят", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
                return;
            }
            Room addRoom = new Room(roomNo, floor);
            dc.Rooms.Add(addRoom);
            dc.SaveChanges();
            roomsViewModel.FillRooms();
            FillRoomsPage();
        }
        else
        {
            MessageBoxResult result = MessageBox.Show("Вы ввели не все данные", "Ошибка", MessageBoxButton.OK, MessageBoxImage.Error);
            return;
        }
    }
    }

Answer the question

In order to leave comments, you need to log in

2 answer(s)
R
Roman, 2019-03-05
@krslnkv

As I understand it, the question is how not to update the RoomsPage separately in the RoomsPageViewModel.
There is one way to avoid this - to remove the excess. The code does not show any special uses for RoomsPage. By making a read-only property that returns roomsViewModel, you can directly bind Rooms to RoomsViewModel. The need for a wrapper through RoomsPage will disappear.

G
GrWizard, 2019-05-07
@GrWizard

if you use\display the same collection in different places, then you need to create at least two collection views for this collection new ListCollectionView(MyObsCollection)and bind it to the ItemsSource (namely, the collection view), the ItemsControl will understand this and will use this particular view, not the default one, then there will be no problems with synchronization and the default representation of the collection.
Otherwise, when the current element changes in 1 listbox or any other ItemsControl, it will automatically change in all the others, unless synchronization is disabled.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question