2015-05-11 6 views
1

Я пишу универсальное приложение с таргетингом на Windows 8.1 и переписываю его для использования контейнера IoC. Однако я нашел кое-что, что меня озадачило.Связывание данных ObservableCollections с IoC

Прежде чем я использовал IoC, я хотел бы создать экземпляр моей VM в коде-позади и привязать к нему, как это:

MainPage.xaml

<ListBox ItemsSource="{Binding ItemList}" DisplayMemberPath="Title" /> 

MainPage. xaml.cs

private MainPageVM Data = new MainPageVM(); 

public MainPage() 
{ 
    this.InitializeComponent(); 
    this.DataContext = Data; 
} 

MainPageVM.cs

public ObservableCollection<MenuItem> ItemList { get; set; } 

public MainPageVM() 
{ 
    ItemList = new ObservableCollection<MenuItem>(); 
} 

Это сработало отлично. Тем не менее, сейчас я настройки приложения очень по-разному, например:

App.xaml.cs

Это создает экземпляр MainPageVM():

MainPageVM.cs

private Frame _Frame; 
private Page _View; 

public ObservableCollection<MenuItem> ItemList { get; set; } 

public MainPageVM(
    Frame frame, 
    Page view) 
{ 
    _Frame = frame; 
    _View = view; 

    _View.DataContext = this; 

    ItemList = new ObservableCollection<MenuItem>(); 
    OnPropertyChanged("ItemList"); 
} 

public void Show() 
{ 
    _Frame.Content = _View; 
    Window.Current.Content = _Frame; 
} 

MainPage.xaml.cs

public MainPage() 
{ 
    this.InitializeComponent(); 
} 

MainPage.xaml не изменяется.

Мой вопрос: зачем мне сигнализировать OnPropertyChanged("ItemList");, чтобы активировать привязку во второй версии, но не в первую очередь? Я здесь что-то не так?

Весь мой репозиторий можно найти на GitHub: Learn OneNote.

ответ

1

Переключение между этими двумя линиями должны это исправить:

_View.DataContext = this; 

и

ItemList = new ObservableCollection<MenuItem>(); 

Что происходит, что вы в настоящее время первый установить DataContext, который вызывает все привязки вида по переоценивать, и только тогда вы изменяете ItemsList. Поскольку сеттер ItemsList не вызывает OnPropertyChanged, представление не обновляется при его изменении. Переключаясь между строками, вы сначала инициализируете контекст данных и только затем переоцениваете привязки.

Более читаемое решение будет включать призыв к OnPropertyChanged в вашем инкубаторе (тогда вам не придется переключаться на линии):

private ObservableCollection<MenuItem> itemList 
public ObservableCollection<MenuItem> ItemList 
{ 
    get { return itemsList; } 
    set 
    { 
     if (itemsList != value) 
     { 
      itemsList = value; 
      OnPropertyChanged("ItemsList"); 
     } 
    } 
} 

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

+0

Вы правы. Теперь я удивляюсь, почему я сам этого не поймал ... – Hosch250

+0

Наблюдаемые элементы наблюдаются, поэтому они автоматически запускают обновления. – Hosch250

+0

@ Hosch250 ObservableCollections реализует 'INotifyCollectionChanged' и уведомляет, когда элемент был добавлен или удален из коллекции. Если вы хотите получить уведомление, когда весь экземпляр коллекции был изменен, вы должны реализовать 'INotifyPropertyChanged' в вашем DataContext и поднять событие изменения свойства для этого свойства. –

1

Это потому, что в первой версии ItemList создавался экземпляром в конструкторе view-model, который сам был сконструирован в инициализации вида до привязки данных. Но во второй версии сначала связаны данные get, а затем вы создаете экземпляр ItemList.

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