2015-01-02 2 views
1

Мне нужно составить список предметов. Я привязал коллекцию пользователей к списку. Все работает хорошо, но элементы в списке не обновляются в режиме реального времени. Они не обновляются вообще с помощью этой привязки. Поэтому, когда я удаляю любого пользователя из списка, список не обновляется, даже если его источник правильно изменен.ItemsSource привязка не обновляет значения

Источник находится в модели просмотра данных по пути DataViewModel.Instance.AllUsers; Всякий раз, когда я добавляю в этот список новый элемент или удаляю его, макет не обновляется. Другие крепления хорошо работают. Я попытался обновить макет списка, повысить событие исходного обновления, другой способ добавления/удаления элементов, но ничего не получилось.

Я пытался отлаживать привязку, но у меня слишком много привязок, чтобы найти ошибку.

Заранее благодарим за полезные советы.

Listbox:

<ListBox x:Name="ListboxUsers" ItemsSource="{Binding Path=AllUsers, Mode=OneWay}" Grid.Column="1" Margin="0" Grid.Row="5" Background="DimGray" BorderThickness="0" Visibility="Hidden" SelectionChanged="ListboxUsers_SelectionChanged"/> 

Code-за:

CatalogueGrid.DataContext = DataViewModel.Instance; //whole view model added as datacontext 

DataViewModel класс:

public class DataViewModel : INotifyPropertyChanged 
{ 
    private static DataViewModel _dataViewModel; 

    private Collection<UserModel> allUsers; 
    public Collection<UserModel> AllUsers 
    { 
     get 
     { 
      return allUsers; 
     } 
     set 
     { 
      allUsers = value; 
      NotifyPropertyChanged("AllUsers"); 
     } 
    } 


    private DataViewModel() 
    { 
     AllUsers = new Collection<UserModel>(); 
    }  

    public event PropertyChangedEventHandler PropertyChanged; 
    private void NotifyPropertyChanged(string info) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(info)); 
     } 
    } 
    . 
    . 
    . 

} 

ответ

5

использование ObservableColLection вместо этого, если Collection которым реализует INotifyCollectionChanged интерфейс:

private ObservableCollection<UserModel> allUsers; 
public ObservableCollection<UserModel> AllUsers 
{ 
    get 
    { 
     return allUsers; 
    } 
    set 
    { 
     allUsers = value; 
     NotifyPropertyChanged("AllUsers"); 
    } 
} 
+2

Правильный ответ, неправильное объяснение. Он реализует 'INotifyCollectionChanged', который заставляет обновления работать. Он * также * реализует 'INotifyPropertyChanged', но это не так важно. – BradleyDotNET

+1

thx ответить обновлен – Usama

+1

Еще одна ничтожная вещь, ее не просто «по умолчанию». «ObservableCollection» реализует интерфейс. Период. Невозможно сделать это * не * реализовать интерфейс. – BradleyDotNET

4

Для изменений в коллекции распространяющихся в пользовательский интерфейс, класс коллекции должен осуществить INotifyCollectionChanged.

Очень полезный класс, который уже реализует это ObservableCollection<T> (MSDN). Используйте это вместо Collection<T>.

3

Вы связали свой ListBox к Collection<T> - это просто список, который не выдает никаких уведомлений связанных свойств, что его содержание имеет изменилось. Следовательно, ваш список не может знать, когда коллекция изменилась.

Вместо этого вы можете использовать ObservableCollection<T> class (или, точнее, любую коллекцию, которая также реализует INotifyCollectionChanged), и изменения будут автоматически распространяться в список.

Обратите внимание, что ваше имущество не имеют быть набраны в качестве ObservableCollection<T>, вы также можете просто объявить общественную собственность как IEnumerable<T> или IList<T>; связывание самостоятельно выяснит, реализует ли возвращаемый класс INotifyCollectionChanged. Таким образом, вы можете бесплатно заменить свой фактический базовый класс коллекции, например, с помощью ReadOnlyObservableCollection<T>, если вы хотите запретить изменения извне.

Говоря об этом, обратите внимание на ваш код: вы предоставили свой AllUsers объект с помощью сеттера. Это может привести к нежелательным последствиям, поскольку вы открываете возможности для какого-либо другого кода, чтобы установить свойство на null, которое (в зависимости от остальной части вашего кода) может привести к исключениям. Если вы действительно не хотите разрешать присвоение новых значений, для привязки свойств ItemsSource, свойство «только для чтения» является полностью достаточным, если возвращаемый объект коллекции реализует INotifyCollectionChanged.

+0

В последнем случае повторное создание коллекции (а не просто добавление/удаление) - это обычная вещь, особенно учитывая накладные расходы на большое количество добавлений/удалений. Да, вы рискуете «пустым», но сеттер - это разумная вещь. – BradleyDotNET

+0

@BradleyDotNET: Хорошо, может быть, это вопрос вкуса. Я вообще избегаю сеттеров для сбора свойств; если вообще, у меня есть какой-то метод, замените экземпляр коллекции. Но чаще всего я предоставляю свои собственные реализации интерфейсов коллекции как вложенные классы, так как это позволяет удобно избегать добавления в коллекцию нежелательных элементов, таких как «null». В любом случае, если вся коллекция обменивается, можно просто вызвать «Очистить», которая запускает событие «CollectionChanged» в режиме «Сброс», а не удаляет отдельные элементы по одному. –

+1

Несомненно, вам все равно придется добавлять все предметы (которые * могут * по-прежнему быть неэффективными по сравнению с одним гигантом). Как вы говорите, в какой-то степени это вопрос вкуса. – BradleyDotNET

Смежные вопросы