使用TabControl和MVVM时绑定丢失

时间:2016-02-18 13:51:35

标签: c# wpf mvvm

我仍然认为自己是MVVM的初学者,我在TabControl中遇到绑定问题。我的应用程序允许用户创建国家和州,输入一些信息,然后将它们保存到数据库中。以下是我的应用程序结构的描述:

基本ViewModel / View称为ApplicationViewModel / ApplicationView。 ApplicationViewModel有一个名为Tabs的ObservableCollection,它包含一个AllNationsViewModel和一个AllStatesViewModel。此Tabs属性绑定到ApplicationView中的TabControl的ItemsSource。

AllNationsViewModel / AllNationsView用于显示用户输入的所有国家/地区。它还允许用户创建新的国家并选择一个特定的国家进行更仔细的检查。 AllStatesViewModel / AllStatesView对状态执行相同操作。

最后,我有一个处理特定国家的NationViewModel / NationsView;此处还有StateViewModel / StateView对状态执行相同的操作。

对于一个国家,你现在只能输入一个名字,但对于一个州,你可以输入一个名字以及它所属的国家。使用ComboBox选择国家,其中所有在国家标签中创建的国家都会出现。

我使用一个名为DataFacade的静态类作为数据存储的接口。可以使用此界面添加,删除和检索国家/州的列表;它也会在添加或删除某些内容时触发事件。

我遇到的问题是,当AllStatesViewModel(CurrentStateViewModel属性)中选择了一个状态,然后我转到NATIONAL选项卡,然后返回状态选项卡,当前选择的状态已失去其国家。所有其他州仍然很难。

我将尝试在下面显示相关代码(我已从某些方法中删除了不相关的代码):

州级:

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

   public Nation Nation { get; set; }
}

ApplicationView中的TabControl:

<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>

当用户创建国家时,会触发AllNationsViewModel的AddCommand:

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

当一个国家/地区被添加到数据存储时,AllStatesViewModel会收到通知:

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

上面的Nations属性是NationViewModels的ObservableCollection。现在,StateView中的ComboBox使用此属性来填充其项目,以便在创建/编辑状态时可以选择国家/地区:

<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>

我认为问题与上面的绑定有关。因为如果我没有绑定到AllStatesViewModel中的Nations属性,而是绑定到ApplicationViewModel中的临时属性,一切正常。当我转到另一个选项卡时,TabControl是否会抛弃AllStatesView,因为上面的绑定将我的StateViewModel的Nation属性设置为null?当我调试时,我看到退出状态选项卡时出现空值。

像我这样的初学者怎么会解决这种情况呢?我发现我的临时解决方案相当丑陋。我不完全确定如何处理数据存储访问,因为我发现的所有MVVM示例都没有关注这一部分。

编辑:根据要求添加一些图片:

Atm我只有最简单的测试GUI设置:

在这里你看到AllNationsView,atm NationView只是“Name”TextBlock和顶部的TextBox。

Nations

这是AllStatesView,顶部是当前选中的状态(使用StateView显示)。你现在看到美国被选为蒙大拿州的国家,如果我进入国家选项卡然后回到州选项卡,蒙大拿州的国家现在是空白的。如果我选择佛罗里达州,它仍然以美国为国家。

States

1 个答案:

答案 0 :(得分:2)

WPF仅保留内存中活动选项卡的UI。当您更改选项卡时,UI将被销毁,并且新选项卡的UI将被创建并反弹。

您可以通过几种方式解决问题。您可以使用存储库模式存储和访问与视图模型分开的数据源。基本上,外部对象保存您的数据源,例如州和国家列表。这样,当活动标签发生变化时,它们就不会被破坏。

另一种选择是将数据源存储在pip install lxml-3.4.4-cp34-none-win_amd64.whl 上,并通过对每个标签的视图模型上的ApplicationViewModel的引用来访问它们。你不应该在那里的任何地方使用ApplicationViewModel绑定。