1. ホーム
  2. c#

TabControlをViewModelsのコレクションにバインドするにはどうしたらいいですか?

2023-10-14 22:33:15

質問

基本的に私はMainViewModel.csで持っています。

ObservableCollection<TabItem> MyTabs { get; private set; }

しかし、タブを作成するだけでなく、タブの内容を読み込んで適切なビューモデルにリンクさせることが、MVVMを維持しながらどうにかできるようにする必要があります。

基本的に、どのように私はユーザーコントロールがタブ項目のコンテンツとしてロードされ、そのユーザーコントロールが適切なビューモデルに配線されるようにすることができます。これを難しくしている部分は、ViewModel が実際のビューアイテムを構築することになっていないことです。それとも、できるのでしょうか?

基本的に、これはMVVM適切であるだろう。

UserControl address = new AddressControl();
NotificationObject vm = new AddressViewModel();
address.DataContext = vm;
MyTabs[0] = new TabItem()
{
    Content = address;
}

私が尋ねるのは、まあ、私はViewModelの中からView(AddressControl)を構築しているので、私にはMVVMの禁句のように聞こえるのですが。

どのように解決するのですか?

これはMVVMではありません。 ビューモデルでUI要素を作ってはいけません。

タブのItemsSourceをObservableCollectionにバインドし、作成すべきタブの情報を持つモデルを保持すべきです。

以下はVMと、タブページを表すモデルです。

public sealed class ViewModel
{
    public ObservableCollection<TabItem> Tabs {get;set;}
    public ViewModel()
    {
        Tabs = new ObservableCollection<TabItem>();
        Tabs.Add(new TabItem { Header = "One", Content = "One's content" });
        Tabs.Add(new TabItem { Header = "Two", Content = "Two's content" });
    }
}
public sealed class TabItem
{
    public string Header { get; set; }
    public string Content { get; set; }
}

そして、バインディングがウィンドウに表示される様子は以下の通りです。

<Window x:Class="WpfApplication12.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <ViewModel
            xmlns="clr-namespace:WpfApplication12" />
    </Window.DataContext>
    <TabControl
        ItemsSource="{Binding Tabs}">
        <TabControl.ItemTemplate>
            <!-- this is the header template-->
            <DataTemplate>
                <TextBlock
                    Text="{Binding Header}" />
            </DataTemplate>
        </TabControl.ItemTemplate>
        <TabControl.ContentTemplate>
            <!-- this is the body of the TabItem template-->
            <DataTemplate>
                <TextBlock
                    Text="{Binding Content}" />
            </DataTemplate>
        </TabControl.ContentTemplate>
    </TabControl>
</Window>

(注意: 異なるタブに異なるものを表示させたい場合は DataTemplates . 各タブのビューモデルはそれ自身のクラスでなければなりません。 DataTemplateSelector を作成して正しいテンプレートを選択するかです)。

データテンプレート内のUserControlです。

<TabControl
    ItemsSource="{Binding Tabs}">
    <TabControl.ItemTemplate>
        <!-- this is the header template-->
        <DataTemplate>
            <TextBlock
                Text="{Binding Header}" />
        </DataTemplate>
    </TabControl.ItemTemplate>
    <TabControl.ContentTemplate>
        <!-- this is the body of the TabItem template-->
        <DataTemplate>
            <MyUserControl xmlns="clr-namespace:WpfApplication12" />
        </DataTemplate>
    </TabControl.ContentTemplate>
</TabControl>