2016-02-18 4 views
4

Я все еще считаю себя новичком, когда дело касается MVVM, и у меня возникла проблема со связыванием в TabControl. Мое приложение позволяет пользователю создавать страны и штаты, вводить некоторую информацию, а затем сохранять их в базе данных. Ниже приведено описание структуры моей заявки:Связывание теряется при использовании TabControl и MVVM

Базовый ViewModel/View называется ApplicationViewModel/ApplicationView. В ApplicationViewModel есть ObservableCollection, называемые вкладками, состоящими из одного AllNationsViewModel и одного AllStatesViewModel. Это свойство Tabs привязано к элементу ItemsSource элемента TabControl в ApplicationView.

AllNationsViewModel/AllNationsView используются для отображения всех стран, которые были введены пользователем. Он также позволяет пользователю создавать новые страны и выбирать конкретную страну для более тщательного изучения. AllStatesViewModel/AllStatesView делает то же самое, но для состояний.

Наконец, у меня есть NationViewModel/NationsView, который имеет дело с определенной нацией; также здесь есть StateViewModel/StateView, которые делают то же самое для состояния.

Для нации вы можете на данный момент ввести только имя, но для состояния вы можете ввести имя, а также страну, в которой она входит. Страна выбирается с помощью ComboBox, где отображаются все народы, созданные на вкладке «Нации».

Я использую статический класс DataFacade в качестве интерфейса с моим хранилищем данных. Можно добавлять, удалять и извлекать список стран/состояний, используя этот интерфейс; также он вызывает события, когда что-то добавляется или удаляется.

Проблема, с которой я столкнулась, заключается в том, что когда в объекте AllStatesViewModel (свойство CurrentStateViewModel) есть состояние, и я перехожу на вкладку стран, а затем обратно на вкладку состояния, текущее выбранное состояние потеряло свою нацию. Все остальные государства все еще в порядке.

Я попытаюсь показать соответствующий код ниже (я удалил ненужный код из некоторых методов):

государственного класс:

class State 
{ 
    public string Name { get; set; } 

    public Nation Nation { get; set; } 
} 

TabControl в ApplicationView:

<TabControl ItemsSource="{Binding Tabs}" Margin="6"> 
    <TabControl.ItemTemplate> 
     <DataTemplate> 
     <ContentPresenter Content="{Binding DisplayName}" /> 
     </DataTemplate> 
    </TabControl.ItemTemplate> 
    <TabControl.ContentTemplate> 
     <DataTemplate> 
     <ContentPresenter Content="{Binding }" /> 
     </DataTemplate> 
    </TabControl.ContentTemplate> 
</TabControl> 

Когда пользователь создает нацию, запускается AddCommand AllNationsViewModel:

private void Add(NationViewModel vm) 
{ 
    DataFacade.AddNation(vm.Nation); 
} 

The AllStatesViewModel получает уведомление, когда страна будет добавлен в хранилище данных:

private void OnDataStoreNationsChanged(object sender, DataFacadeEventArgs e) 
{ 
    Nations.Add(new NationViewModel(e.Context as Nation)); 
} 

Имущество Наций выше является ObservableCollection из NationViewModels. Теперь это свойство используется ComboBox в StateView, чтобы заполнить его элементы так нация может быть выбрана при создании/редактировании состояния:

<ComboBox Grid.Row="1" Grid.Column="1" SelectedValue="{Binding Nation}" SelectedValuePath="Nation" ItemsSource="{Binding DataContext.Nations, RelativeSource={RelativeSource AncestorType={x:Type local:AllStatesView}}}"> 
    <ComboBox.ItemTemplate> 
     <DataTemplate> 
     <TextBlock Text="{Binding Name}" /> 
     </DataTemplate> 
    </ComboBox.ItemTemplate> 
</ComboBox> 

Я считаю, что проблема связана с вышеназванным связывания. Потому что, если я не привязываюсь к свойству Nations в AllStatesViewModel, но вместо этого привязываюсь к временному свойству в ApplicationViewModel, все работает. Может ли быть, что AllStatesView выбрасывается TabControl, когда я перехожу на другую вкладку, поэтому привязка выше устанавливает свойство Nation моего StateViewModel равным null? Когда я отлаживаю, я вижу, что при выходе из вкладки состояния я получаю нуль.

Как бы тот, кто не является новичком, как я, решает эту ситуацию? Я нахожу свое временное решение довольно уродливым. Я не совсем уверен, как я должен обращаться с доступом к хранилищу данных, поскольку все найденные мной MVVM-объекты не фокусируются на этой части.

EDIT: Addded несколько фотографий по запросу:

Банкоматы Я просто самый простой GUI тестирование настройки:

Здесь вы видите AllNationsView, атм NationView лишь «Name» TextBlock и TextBox наверху.

Nations

Здесь AllStatesView, на самом верху выбранный в данный момент состояние (отображается с использованием StateView). Где вы теперь видите, что США выбраны в качестве нации для Монтаны, если я перейду на вкладку «Нации», а затем вернусь на вкладку «Штаты», нация для Монтаны теперь пуста. Если я выберу Флориду, у нее все еще есть США как ее нация.

States

+0

Мне нелегко визуализировать настройку, которую вы описываете. Не могли бы вы опубликовать несколько скриншотов? –

+0

@BradleyUffner Я добавил две фотографии сейчас. Надеюсь, теперь яснее, что я пытаюсь сделать. – dbostream

+0

Спасибо, это намного яснее. –

ответ

2

WPF только сохраняет пользовательский интерфейс для активной вкладки в памяти. При изменении вкладок, которые пользовательский интерфейс уничтожен, и пользовательский интерфейс новой вкладки создается и восстанавливается.

Существует несколько способов устранения проблемы, с которой вы сталкиваетесь. Шаблон репозитория можно использовать для хранения и доступа к источникам данных отдельно от моделей просмотра. В основном внешний объект хранит ваши источники данных, такие как списки государств и стран. Таким образом, они не уничтожаются при изменении активной вкладки.

Другой вариант - хранить источники данных на вашем ApplicationViewModel и получать к ним доступ по ссылкам на ApplicationViewModel в каждой модели просмотра каждой отдельной вкладки. Вам не нужно использовать привязку RelativeSource в любом месте.

+0

Спасибо за предложения. Что касается шаблона репозитория, похоже, что у меня есть что-то подобное в классе DataFacade. Это внешний объект, который хранит все мои модели (нации и государства), и я могу получить их все в виде списков. Я попытался переместить свойство Nations из AllStatesViewModel в StateViewModel, тем самым устраняя необходимость связывания RelativeSource для ComboBox, и теперь он работает. В любом случае AllStatesViewModel не использовал свойство Nations для чего-либо еще. – dbostream

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