web-dev-qa-db-ja.com

TabItemにUserControlをロードします

TabControlを含むUsercontrol(TabUserControl)があります。そのUserControlのViewmodelは、TabItemのObservableコレクションをロードします。 1つのodこれらのアイテムは別のユーザーコントロールです。タブコントロールにテキストをロードするだけでは問題はありませんが、他のユーザーコントロールをTabUserControlのタブアイテムにロードするにはどうすればよいですか。私はMVVMを使用します。

これが私のコードです:

public class TabItem
{
    public string Header { get; set; }
    public object Content { get; set; } // object to allow all sort of items??
}

TabUserControlのビューモデル

public class TabViewModel
{
    public ObservableCollection<TabItem> Tabs {get;set;}

    public TabViewModel()
    {
        Tabs = new ObservableCollection<TabItem>();
        //Tabs.Add(new TabItem { Header = "Overview", Content = new OverviewViewModel() }); How to load a usercontrol here if it's in the ItemCollection?
        Tabs.Add(new TabItem { Header = "Overview", Content = "Bla bla bla" });
        Tabs.Add(new TabItem { Header = "Two", Content = "Two's content" });
    }
}

そして、TabControl XAML:

<TabControl x:Name="_tabControl"
            ItemsSource="{Binding Tabs}">
  <TabControl.ItemContainerStyle>
    <Style TargetType="TabItem">
      <Setter Property="Header"
              Value="{Binding Header}" />
      <Setter Property="Content"
              Value="{Binding Content}" />
    </Style>
  </TabControl.ItemContainerStyle>
</TabControl>

TabItemsコレクションにユーザーコントロールのビューモデルをロードしない限り、機能します。 UserTabControlをTabItemにロードするにはどうすればよいですか?すべてのタブアイテムにユーザーコントロールが含まれるようにすることを目的としています。次に、各ユーザーコントロールは独自のことを行います。

私はWPFの初心者なので、誰かが私を助けてくれることを願っています。どうも!

13
PitAttack76

理想的には、TabControl.ItemsSourceViewModelsのコレクションに設定する必要があり、DataTemplatesは、特定のViewModelで各UserControlを描画するようにWPFに指示するために使用する必要があります。

これにより、ビジネスロジック(ViewModels)とUI(Views)が完全に分離されます。

例えば、

<TabControl x:Name="MyTabControl"
            ItemsSource="{Binding TabViewModels}"
            SelectedItem="{Binding SelectedTabViewModel}">

    <TabControl.Resources>
        <DataTemplate DataType="{x:Type my:ViewModelA}">
            <my:ViewAUserControl />
        </DataTemplate>
        <DataTemplate DataType="{x:Type my:ViewModelB}">
            <my:ViewBUserControl />
        </DataTemplate>
        <DataTemplate DataType="{x:Type my:ViewModelC}">
            <my:ViewCUserControl />
        </DataTemplate>
    </TabControl.Resources>

    <TabControl.ItemContainerStyle>
        <Style TargetType="TabItem">
            <Setter Property="Header" Value="{Binding Header}" />
        </Style>
    </TabControl.ItemContainerStyle>

</TabControl>

TabControlのDataContextを含むViewModel:

TabViewModels = new ObservableCollection<ITabViewModel>();
TabViewModels.Add(new ViewModelA { Header = "Tab A" });
TabViewModels.Add(new ViewModelB { Header = "Tab B" });
TabViewModels.Add(new ViewModelC { Header = "Tab C" });

SelectedTabViewModel = TabViewModels[0];
35
Rachel

レイチェルに答えてくれてありがとう。ただし、コンパイル時自体にDataContextの宣言を強制します。あなたがしたように、各ビューをTabControlのDataTemplate内のそれぞれのViewModelに関連付けます。これをViewModelに移動すると、動的なView-ViewModelリンクを実現できます。方法は次のとおりです。

XAML:

<TabControl.ItemContainerStyle>
                <Style TargetType="TabItem">
                    <Setter Property="Header" Value="{Binding Header}" />
                    <Setter Property="Content" Value="{Binding Content}" />
                </Style>
            <TabControl.ItemContainerStyle>

VM:

 public ObservableCollection<TabItem> TabItems { get; set; }
 public MainWindowViewModel()
        {
            TabItems = new ObservableCollection<TabItem>
            {
                new TabItem{Content = new TabAView() {DataContext = new TabAViewModel()}, Header = "Tab A"},
                new TabItem{Content = new TabBView(), Header = "Tab B"}
            };
        }

アクションデリゲートを使用して、TabSelectionChangedEventでのみTabItemの初期化を遅延および呼び出すこともできます。これにより、UserControlビューに多くのUI要素がある場合、多くのメモリを節約できます。

4