3

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

保存选项卡集合的 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)存在哪些使用此概念的“解决方法”,允许我存储给定选项卡的“视觉树”,因此如果我离开它然后重新打开它,它将存储所有信息(例如选择复选框、书面文本等)

非常感谢您对此事的任何帮助。

问候,伊丹

4

2 回答 2

3

问题的解决方案是扩展 TabControl 并替换默认行为,这样它就不会卸载旧选项卡。最终解决方案(包含控件和控件模板)是 @Stop TabControl 重新创建其子项

感谢 Shoe 为我指明了最终解决方案的正确方向:)

于 2013-09-19T09:33:25.267 回答
0

我有类似的问题,我想出了这个解决方案

    void OnAddWorkSpace(object Sender, EventArgs e)
    {
        WorkspaceViewModel loclViewModel = (e as WorkSpaceEventArgs).ViewModel;
        DataTemplate loclTemplate = (DataTemplate)Resources[new DataTemplateKey(loclViewModel.GetType())];

        if (loclTemplate != null)
        {
            DXTabItem loclTabItem = new DXTabItem();
            loclTabItem.Content = loclTemplate.LoadContent();
            (loclTabItem.Content as DependencyObject).SetValue(DataContextProperty, loclViewModel);
            loclTabItem.HeaderTemplate = (DataTemplate)FindResource("WorkspaceItemTemplate");
            loclTabItem.Header = (loclTabItem.Content as DependencyObject).GetValue(DataContextProperty);
            MainContentTabs.Items.Add(loclTabItem);
        }
    }

我在 ViewModel 中创建了一个事件处理程序,并且我的 View 订阅了它。我的 ViewModel 对象被添加到集合中。现在,每当添加 ViewModel 时,我的 MainViewModel 都会调用这个偶数处理程序。

在这里,我们需要找到为要添加的 ViewModel 的 DataType 定义的 DataTemplate。一旦我们掌握了这一点,我们就可以创建一个选项卡项,然后从数据模板中加载内容。

因为我使用的是 DevExpress TabControl,所以我创建了 DXTabItem。TabItem 也应该同样工作。

于 2014-01-08T20:16:57.640 回答