3

「TabViewModelItem」のコレクションにバインドされたTabControlを保持するMVVMパターンを使用して、WPFアプリケーションを作成しました。

メイン ウィンドウの 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 がその子を再作成しないようにすることです。

最終的な解決策につながる正しい方向に私を向けてくれた靴に感謝します:)

于 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 に答える