我仍然认为自己是 MVVM 的初学者,并且我在 TabControl 中遇到了绑定问题。我的应用程序允许用户创建国家和州,输入一些信息,然后将它们保存到数据库中。下面是我的应用程序结构的描述:
基础 ViewModel/View 称为 ApplicationViewModel/ApplicationView。ApplicationViewModel 有一个名为 Tabs 的 ObservableCollection,由一个 AllNationsViewModel 和一个 AllStatesViewModel 组成。此 Tabs 属性绑定到 ApplicationView 中的 TabControl 的 ItemsSource。
AllNationsViewModel/AllNationsView 用于显示用户输入的所有国家。它还允许用户创建新的国家并选择一个特定的国家进行仔细检查。AllStatesViewModel/AllStatesView 做同样的事情,但对于状态。
最后,我有处理特定国家的 NationViewModel/NationsView;这里还有 StateViewModel/StateView 对状态做同样的事情。
对于一个国家,您目前只能输入一个名称,但对于一个州,您可以输入一个名称以及它所属的国家。使用组合框选择国家,其中显示在国家选项卡中创建的所有国家。
我使用名为 DataFacade 的静态类作为数据存储的接口。可以使用此界面添加、删除和检索国家/地区列表;它还会在添加或删除某些内容时触发事件。
我遇到的问题是,当在 AllStatesViewModel(CurrentStateViewModel 属性)中选择了一个州时,我转到国家选项卡,然后返回到状态选项卡,当前选定的州已经失去了它的国家。所有其他州仍然很艰难。
我将尝试在下面显示相关代码(我已从某些方法中删除了不相关的代码):
状态类:
class State
{
public string Name { get; set; }
public Nation Nation { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
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>
Run Code Online (Sandbox Code Playgroud)
当用户创建一个国家时,AllNationsViewModel 的 AddCommand 被触发:
private void Add(NationViewModel vm)
{
DataFacade.AddNation(vm.Nation);
}
Run Code Online (Sandbox Code Playgroud)
当一个国家被添加到数据存储时, AllStatesViewModel 会收到通知:
private void OnDataStoreNationsChanged(object sender, DataFacadeEventArgs e)
{
Nations.Add(new NationViewModel(e.Context as Nation));
}
Run Code Online (Sandbox Code Playgroud)
上面的国家属性是 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>
Run Code Online (Sandbox Code Playgroud)
我相信问题与上面的绑定有关。因为如果我不绑定到 AllStatesViewModel 中的 Nations 属性,而是绑定到 ApplicationViewModel 中的一个临时属性,一切都会正常。当我转到另一个选项卡时,AllStatesView 是否会被 TabControl 丢弃,因为上面的绑定将我的 StateViewModel 的 Nation 属性设置为 null?当我调试时,我看到退出状态选项卡时得到一个空值。
像我这样不是初学者的人如何解决这种情况?我发现我的临时解决方案相当丑陋。我不完全确定我应该如何处理数据存储访问,因为我发现的所有 MVVM 示例都没有关注这一部分。
编辑:按要求添加了一些图片:
Atm 我只有最简单的测试 GUI 设置:
在这里你看到 AllNationsView,atm NationView 只是“名称”TextBlock 和顶部的 TextBox。
这里是AllStatesView,顶部是当前选中的状态(使用StateView显示)。现在您看到美国被选为蒙大拿州的国家,如果我转到国家选项卡,然后返回州选项卡,蒙大拿州的国家现在是空白的。如果我选择佛罗里达州,它的国家仍然是美国。
WPF 仅将活动选项卡的 UI 保留在内存中。当您更改选项卡时,UI 会被销毁,新选项卡的 UI 会被创建并反弹。
有几种方法可以解决您遇到的问题。您可以使用存储库模式来独立于视图模型来存储和访问数据源。基本上,外部对象保存您的数据源,例如州和国家列表。这样,当活动选项卡发生更改时,它们就不会被破坏。
另一个选项是将数据源存储在您的数据源上ApplicationViewModel,并通过对每个单独选项卡的视图模型的引用来访问它们ApplicationViewModel。您不必RelativeSource在其中的任何地方使用绑定。
| 归档时间: |
|
| 查看次数: |
727 次 |
| 最近记录: |