首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >WPF TabControl -添加带有内容模板的新选项卡

WPF TabControl -添加带有内容模板的新选项卡
EN

Stack Overflow用户
提问于 2022-05-08 03:11:06
回答 1查看 150关注 0票数 -1

我试图制作一个演示应用程序来帮助我理解WPF/MVVM。3天来,我一直在努力学习各种教程和线程。我希望使用一个新的选项卡按钮(如这里)来创建一个选项卡控件,该按钮允许用户创建一个具有指定内容模板的新选项卡。我在这里创建了我想要成为模板的用户控件:

代码语言:javascript
运行
复制
<UserControl x:Class="MvvmTest.UserControl1"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:MvvmTest"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <ListView d:ItemsSource="{d:SampleData ItemCount=5}">
            <ListView.View>
                <GridView>
                    <GridViewColumn/>
                </GridView>
            </ListView.View>
        </ListView>

    </Grid>
</UserControl>

它只是一个带有ListView的控件。因此,我希望这个ListView在打开的任何新选项卡中。

下面是带有实际选项卡控件的主窗口:

代码语言:javascript
运行
复制
<Window x:Class="MvvmTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:MvvmTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Button Content="New Tab" Margin="703,6,10,401" Click="Button_Click"/>

        <TabControl Name= "TabControl1" Margin="0,33,0,-33" Grid.ColumnSpan="2">
        
        </TabControl>

    </Grid>
</Window>

在此代码隐藏中,我尝试以编程方式创建一个新选项卡,并将内容模板设置为新控件。

代码语言:javascript
运行
复制
private void Button_Click(object sender, RoutedEventArgs e)
{
    TabControl1.Items.Add(new TabItem() { ContentTemplate = UserControl1 });
}

这是失败的。我还尝试在同样失败的XAML中设置属性。我不知道还能尝试什么。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-05-08 07:00:31

如果您试图使用MVVM,您的视图模型在哪里?到目前为止,您使用的方法并不是MVVM,因为您正在使用代码隐藏来添加选项卡项。MVVM的方法是将TabControlTabControl属性绑定到一个项集合,并让视图模型为您添加这些项。如果不将UserControl包装在DataTemplate定义中,您也不能将它用作这样的ContentTemplate

首先要做的是定义一些视图模型:

代码语言:javascript
运行
复制
// MvvmLight (from NuGet) is included for it's INotifyPropertyChanged
// (ViewModelBase) and ICommand (RelayCommand) classes. INotifyPropertyChanged
// is how Binding works between the View and the View Model. You could 
// implement these interfaces yourself if you wanted to. 
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;

using System.Collections.ObjectModel;
using System.Windows.Input;


namespace MvvmTest
{
    public class MainWindowViewModel : ViewModelBase
    {
        // store our list of tabs in an ObservableCollection
        // so that the UI is notified when tabs are added/removed
        public ObservableCollection<TabItemViewModel> Tabs { get; }
            = new ObservableCollection<TabItemViewModel>();

        // this code gets executed when the button is clicked
        public ICommand NewTabCommand 
            => new RelayCommand(() => Tabs.Add(new TabItemViewModel() 
               { Header = $"Tab {Tabs.Count + 1}"})); 
    }

    public class TabItemViewModel : ViewModelBase
    {
        // this is the title of the tab, note that the Set() method
        // invokes PropertyChanged so the view knows if the 
        // header changes
        public string Header
        {
            get => _header;
            set => Set(ref _header, value);
        }
        private string _header;

        // these are the items that will be shown in the list view
        public ObservableCollection<string> Items { get; } 
            = new ObservableCollection<string>() { "One", "Two", "Three" };
    }
}

然后,您可以修复XAML,以便它引用您定义的视图模型。这需要为您的DataContext定义MainWindow,并将MainWindow元素绑定到视图模型上的属性:

代码语言:javascript
运行
复制
<Window x:Class="MvvmTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:MvvmTest"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <!--Set the DataContent to be an instance of our view-model class -->
        <local:MainWindowViewModel/>
    </Window.DataContext>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!--The Command of the button is bound to the View Model -->
        <Button Grid.Row="0" HorizontalAlignment="Right" Width="100"  
                Content="New Tab" 
                Command="{Binding NewTabCommand}" />

        <!--ItemsSource is bound to the 'Tabs' property on the view-
            model, while DisplayMemeberPath tells TabControl 
            which property on each tab has the tab's name -->
        <TabControl Grid.Row="1" 
                    ItemsSource="{Binding Tabs}" 
                    DisplayMemberPath="Header">

            <!--Defining the ContentTemplate in XAML when is best.
                This template defines how each 'thing' in the Tabs 
                collection will be presented. -->
            <TabControl.ContentTemplate>
                <DataTemplate>
                    <!--The UserControl/Grid were pointless, so I 
                        removed them. ItemsSource of the ListView is 
                        bound to an Items property on each object in
                        the Tabs collection-->
                    <ListView ItemsSource="{Binding Items}">
                        <ListView.View>
                            <GridView>
                                <GridViewColumn Header="Some column"/>
                            </GridView>
                        </ListView.View>
                    </ListView>
                </DataTemplate>
            </TabControl.ContentTemplate>
        </TabControl>

    </Grid>
</Window>

结果是,当您按下按钮时,会创建一个新的选项卡并显示。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72157780

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档