【发布时间】:2013-09-07 14:22:13
【问题描述】:
我使用 MVVM 模式编写了一些 WPF 应用程序,其中包含绑定到“TabViewModelItem”集合的 TabControl。
XAML 主窗口:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ViewModel="clr-namespace:XcomSavesGameEditor.ViewModel"
x:Class="XcomSavesGameEditor.MainWindow"
xmlns:Views="clr-namespace:XcomSavesGameEditor.View"
Title="X-COM Saved Game Editor" Height="650" Width="850" Background="#FF1B0000">
<Window.DataContext>
<ViewModel:TabsManagerViewModel/>
</Window.DataContext>
<Grid>
... (some not relevant code removed for clearity of question) ...
<TabControl x:Name="myTabs" Background="Black" Margin="0,25,0,0" BorderThickness="0,0,0,0" BorderBrush="Black" ItemsSource="{Binding Tabs}" >
<TabControl.Resources>
<DataTemplate DataType="{x:Type ViewModel:Tab0a_FileSaveData_ViewModel}">
<Views:Tab0a_FileSaveData_View />
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModel:Tab0b_Summary_ViewModel}">
<Views:Tab0b_Summary_View />
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModel:Tab1_Research_ViewModel}">
<Views:Tab1_Research_View />
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModel:Tab2_Engineering_ViewModel}">
<Views:Tab2_Engineering_View />
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModel:Tab3_Barracks_ViewModel}">
<Views:Tab3_Barracks_View />
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModel:Tab4_Hangar_ViewModel}">
<Views:Tab4_Hangar_View />
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModel:Tab5_SituationRoom_ViewModel}">
<Views:Tab5_SituationRoom_View />
</DataTemplate>
</TabControl.Resources>
<TabControl.ItemTemplate>
<!-- this is the header template-->
<DataTemplate>
<Grid Margin="0">
<Border Margin="0,0,0,0"
Background="Black"
BorderBrush="Black"
BorderThickness="0,0,0,0" Padding="0,0,0,0">
<StackPanel Orientation="Horizontal"
Margin="0,0,0,0">
<Image Name ="tabImage" Source="{Binding TabImage_Disabled}" />
</StackPanel>
</Border>
</Grid>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Path=IsSelected,RelativeSource={RelativeSource TemplatedParent}}" Value="True">
<Setter TargetName="tabImage" Property="Source" Value="{Binding TabImage_Enabled}"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<!-- this is the body of the TabItem template-->
<DataTemplate>
<Grid>
<Grid.Background>
<ImageBrush ImageSource="{Binding TabImage_Background}"/>
</Grid.Background>
<UniformGrid>
<ContentPresenter HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Content="{Binding TabContents}" />
</UniformGrid>
</Grid>
</DataTemplate>
</TabControl.ContentTemplate>
</TabControl>
而持有tab集合的ViewModel是代码:
public sealed class TabsManagerViewModel : ViewModelBase
{
private ObservableCollection<TabViewModelItem> _tabs;
public ObservableCollection<TabViewModelItem> Tabs
{
get { return _tabs; }
set
{
_tabs = value;
RaisePropertyChanged("Tabs");
}
}
public TabsManagerViewModel()
{
Tabs = new ObservableCollection<TabViewModelItem>();
Tabs.Add(new TabViewModelItem { TabName = "File_Save_Data", TabImage_Enabled = _aEnabledTabImages[(int)enum_Tabs.SaveFileData_Tab], TabImage_Disabled = _aDisabledTabImages[(int)enum_Tabs.SaveFileData_Tab], TabImage_Background = _aBackgroundTabImages[(int)enum_Tabs.SaveFileData_Tab], TabContents = new Tab0a_FileSaveData_ViewModel() });
Tabs.Add(new TabViewModelItem { TabName = "Summary", TabImage_Enabled = _aEnabledTabImages[(int)enum_Tabs.Summary_Tab], TabImage_Disabled = _aDisabledTabImages[(int)enum_Tabs.Summary_Tab], TabImage_Background = _aBackgroundTabImages[(int)enum_Tabs.Summary_Tab], TabContents = new Tab0b_Summary_ViewModel() });
... (rest of code removed for clearity of question)
}
}
所以基本上它是绑定到“TabViews”集合的选项卡控件。 并根据对象数据类型显示 View1 或 View2。 注意:View1 和 View 2 是 UserControls,每个都绑定到自己的 ViewModel。 这个概念很好用。
现在你问我的问题在哪里? 我的问题是: 每次我单击另一个选项卡然后返回到同一个选项卡时,我都会再次调用该特定选项卡 ViewModel 构造函数,正如我所期望的那样,ViewModel 对象将保留。
这是个问题,因为当我在选项卡之间切换时,它会导致我丢失在该页面上所做的任何修改。而且由于 ctor 每次都被一遍又一遍地调用,我什至不能使用 VIewModel 来存储这些信息。
我的问题是: 1)有什么方法可以阻止 TabControl 在选项卡处于非活动状态时处理 ViewModel 对象?意味着预先创建所有 ViewModel 的对象而不是在隐藏时处理它们? 2)存在哪些使用此概念的“解决方法”,允许我存储给定选项卡的“视觉树”,因此如果我离开它然后重新打开它,它将存储所有信息(例如选择复选框、书面文本等)
如果有任何帮助,我们将不胜感激。
问候, 伊丹
【问题讨论】:
-
我看过那篇文章,但恐怕我看不到“WpfApplicationFramework”中的“writer”示例如何解决这个问题,因为它对所有文档使用单一视图,其中- 因为我为每个选项卡使用单独的视图(每个都绑定到它自己的视图模型)。
-
那么这个问题可能更合适。 stackoverflow.com/questions/8808076/…
-
谢谢 :) 听起来方向正确,我会检查一下。会随着我的进展发布回复。
-
templateSelector 解决方案不起作用(仍然在每个选项卡之间切换视图模型)。我现在要试试 TabControlEx 类解决方案,会更新它
-
TabControlEx 工作,但您提供的链接没有解决它,因为它只是“部分”解决方案。它缺少可以正常工作的控件样式模板,这是我通过 google @stackoverflow.com/questions/9794151/… 发现的。再次感谢:)
标签: wpf mvvm viewmodel tabcontrol