c# - 在运行时动态更新 TabControl 内容

标签 c# .net wpf

那么问题来了。我有一个分为三个面板的窗口。中间包含一个绘图表面,左侧包含一个选项卡控件。选项卡控件的每个选项卡都包含一个按钮列表,这些按钮必须在右侧面板中打开新菜单。我不知道如何在代码中执行此操作,所以我求助于在运行时在 C# 中单独创建每个按钮。似乎必须有更好的方法来解决它。我目前为按钮单击事件调用以下函数,以在运行时在名为“tabctrl”的 TabControl 右侧面板中绘制不同的菜单。它需要一个字符串参数来指定要绘制的菜单集,尽管此时我只为其中一个菜单编写了代码。下面是函数和 xml 的代码。有没有更好的方法来解决这个问题?

xml:

<TabControl DockPanel.Dock="Right" Background="White" x:Name="tabctrl">
        <TabItem Height ="38" Name="Tab1" Header="tab3"/>
    </TabControl>

c#:

private void menuOpen(string menuSelected)
    {

        //Logic statement for what menu is being opened
        switch (menuSelected)
        {
            case "BackGround":
                {
                    //Remove Current Tabs


                    //Initialize Tab Item, set title, and add tab item to tab control
                    TabItem BackGround = new TabItem();
                    BackGround.Header = "BackGround";
                    tabctrl.Items.Insert(1, BackGround);
                    BackGround.Height = 38;

                    //Initialize Stack Panel, set orientation, and add to tab control
                    StackPanel panel = new StackPanel();
                    panel.Orientation = Orientation.Vertical;
                    BackGround.Content = panel;

                    //Initialize Menu Items
                    Button AddMap = new Button();
                    Button AddDemoMap = new Button();
                    Button RemoveMap = new Button();
                    Button MoveSelected = new Button();
                    Button Properties = new Button();
                    Button ScaleBackground = new Button();

                    //Define Button Text
                    AddMap.Content = "Add Map";
                    AddDemoMap.Content = "Add Demo Map";
                    RemoveMap.Content = "Remove Map";
                    MoveSelected.Content = "Move Selected Map to Top of List";
                    Properties.Content = "Properties";
                    ScaleBackground.Content = "Scale Background to Pipes";

                    AddMap.Height = 50;
                    AddDemoMap.Height = 50;
                    RemoveMap.Height = 50;
                    MoveSelected.Height = 50;
                    Properties.Height = 50;
                    ScaleBackground.Height = 50;

                    //Add Buttons to StackPanel
                    panel.Children.Add(AddMap);
                    panel.Children.Add(AddDemoMap);
                    panel.Children.Add(RemoveMap);
                    panel.Children.Add(MoveSelected);
                    panel.Children.Add(Properties);
                    panel.Children.Add(ScaleBackground);
                }
                break;

最佳答案

好的...让我们看看:

首先,您必须学会以抽象的方式思考您的用户界面:

What is a TabControl?

它是小部件列表的图形表示,其中用户一次可以拥有 1 个事件小部件。这些小部件具有标题(选项卡项文本)、可见性状态和启用/禁用状态。

What is a bunch of stacked buttons? (toolbar, if you want to call it that)

它是用户可以在任何给定时间执行的操作列表的图形表示。这些操作有一个描述(按钮的内容),可能有一个关联的图标或图形图像,以及一个启用/禁用状态。

What is a ContextMenu, or a Menu?

与上面相同,它是用户可以执行的操作列表的图形表示。

How would I go about creating a dynamic TabControl in WPF?

这是支持动态子项的 WPF TabControl 的 XAML:

<Window x:Class="WpfApplication4.Window12"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window12" Height="300" Width="300">
    <Window.Resources>
        <BooleanToVisibilityConverter x:Key="BoolToVisibilityConverter"/>
    </Window.Resources>
        <TabControl ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}">
            <TabControl.ItemContainerStyle>
                <Style TargetType="TabItem">
                    <Setter Property="IsEnabled" Value="{Binding IsEnabled}"/>
                    <Setter Property="Visibility" Value="{Binding IsVisible, Converter={StaticResource BoolToVisibilityConverter}}"/>
                    <Setter Property="Header" Value="{Binding Title}"/>
                </Style>
            </TabControl.ItemContainerStyle>
        </TabControl>
</Window>

View 模型:

 public class TabbedViewModel: ViewModelBase
    {
        private ObservableCollection<TabViewModel> _items;
        public ObservableCollection<TabViewModel> Items
        {
            get { return _items ?? (_items = new ObservableCollection<TabViewModel>()); }
        }

        private ViewModelBase _selectedItem;
        public ViewModelBase SelectedItem
        {
            get { return _selectedItem; }
            set
            {
                _selectedItem = value;
                NotifyPropertyChange(() => SelectedItem);
            }
        }
    }

    public class TabViewModel: ViewModelBase
    {
        private string _title;
        public string Title
        {
            get { return _title; }
            set
            {
                _title = value;
                NotifyPropertyChange(() => Title);
            }
        }

        private bool _isEnabled;
        public bool IsEnabled
        {
            get { return _isEnabled; }
            set
            {
                _isEnabled = value;
                NotifyPropertyChange(() => IsEnabled);
            }
        }

        private bool _isVisible;
        public bool IsVisible
        {
            get { return _isVisible; }
            set
            {
                _isVisible = value;
                NotifyPropertyChange(() => IsVisible);
            }
        }
    }

在这个例子中,TabControl 中的每个项目 (TabItem) 都将绑定(bind)到其中一个 ViewModel,然后只需为每个选项卡继承基础 TabViewModel 并创建适当的 DataTemplate 每个。

如您在此示例中所见,我绝不会在代码中创建或操作任何 UI 元素。这大大简化了所有代码,并有助于在逻辑和 UI 之间保持清晰的分离。 您可以将相同的概念应用于 WPF 中的所有内容。

关于c# - 在运行时动态更新 TabControl 内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15209870/

相关文章:

c# - 使用后期绑定(bind)创建和填充 Excel 工作表

c# - 如何使用 LINQ 枚举字典

c# - 在 C# 中比较两个 SQL Server 数据库模式

c# - 在 WPF 中构建自定义主题或使用标准主题

.net - 在Message.CreateMessage中, "action"参数是什么意思?

c# - Visual Studio 2015 企业版和混合版?

c# - 如何防止 PropertyChanged 在控件初始化时触发

c# - 初始化 KeyValuePair 数组

.net - 检测并重新启动我崩溃的 .NET 应用程序

wpf - 如何使用可忽略的 ="d"