Как заставить ItemsSource обновить свою привязку?

StackOverflow https://stackoverflow.com/questions/806714

  •  03-07-2019
  •  | 
  •  

Вопрос

У меня есть представление, в котором отображается поле списка, которое привязано к GetAll():

<DockPanel>
    <ListBox ItemsSource="{Binding GetAll}"
             ItemTemplate="{StaticResource allCustomersDataTemplate}"
             Style="{StaticResource allCustomersListBox}">
    </ListBox>
</DockPanel>

GetAll() - это свойство ObservableCollection на мой взгляд, модель:

public ObservableCollection<Customer> GetAll
{
    get
    {
        return Customer.GetAll();
    }
}

который, в свою очередь вызывает метод модели GetAll() который считывает XML-файл для заполнения ObservableCollection.:

public static ObservableCollection<Customer> GetAll()
{
    ObservableCollection<Customer> customers = new ObservableCollection<Customer>();

    XDocument xmlDoc = XDocument.Load(Customer.GetXmlFilePathAndFileName());
    var customerObjects = from customer in xmlDoc.Descendants("customer")
                          select new Customer
                          {
                              Id = (int)customer.Element("id"),
                              FirstName = customer.Element("firstName").Value,
                              LastName = customer.Element("lastName").Value,
                              Age = (int)customer.Element("age")
                          };
    foreach (var customerObject in customerObjects)
    {
        Customer customer = new Customer();

        customer.Id = customerObject.Id;
        customer.FirstName = customerObject.FirstName;
        customer.LastName = customerObject.LastName;
        customer.Age = customerObject.Age;

        customers.Add(customer);
    }

    return customers;
}

Все это работает нормально, ЗА исключением случаев, когда пользователь переходит к другому представлению, редактирует XML-файл и возвращается к этому представлению , где старые данные все еще отображаются.

Как я могу сказать этому представлению "обновить свои привязки", чтобы оно показывало фактические данные?

Такое ощущение, что я говорю о WPF здесь со слишком большой метафорой HTML / HTTP, я чувствую, что есть более естественный способ заставить ObservableCollection обновлять себя, отсюда и его название, но это единственный способ, которым я могу заставить пользователя редактировать данные в приложении WPF на данный момент.Так что здесь ценится помощь на любом уровне.

Это было полезно?

Решение

Ан ItemsControl запрашивает его привязку один раз и после этого кэширует ссылку.

Если содержимое объекта коллекции изменено, и он реализует INotifyCollectionChanged (как ObservableCollection делает), он подберет любой добавленный или удаленный объект.

Теперь, если вы хотите, чтобы привязка предоставила новый объект коллекции в ListBox, вы можете реализовать свою view-модель INotifyPropertyChanged и поднять PropertyChanged, проходящий в GetAll в качестве имени свойства.Это приведет к предупреждению привязки о том, что значение свойства изменилось (появилось новое ObservableCollection готов к приему), который он будет поставлять в ListBox, который повторно сгенерирует свои элементы.

Таким образом, до тех пор, пока вы вносите изменения в свое приложение, работая над ObservableCollection возвращенный GetAll, вы можете добавлять и удалять, и список останется синхронизированным.Если вы хотите внести внешние изменения (возможно, у вас где-то есть кнопка обновления или естественная точка, где имеет смысл перезагрузить весь файл), вы можете попросить свою view-model поднять PropertyChanged событие, которое автоматически вызовет средство получения свойства, которое вызовет статический метод, который вернет свежую новую коллекцию.

Замечание придирчивого критика:почему вы даете имена методов свойствам?

Другие советы

Строка ниже работает так же, как при удалении для добавления объекта в коллекцию:

CollectionViewSource.GetDefaultView(CustomObservableCollection).Refresh();

Сохраните ссылку на свой ObservableCollection и время последнего изменения XML-файла на момент его загрузки.Всякий раз, когда окно попадает в фокус, проверяйте временную метку в файле на диске.Если оно было изменено, очистите и повторно заполните ObservableCollection.Графический интерфейс автоматически отслеживает события изменения из ObservableCollection и будет повторно заполняться автоматически при изменении содержимого коллекции.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top