动态更新的TabControl内容在运行时动态、内容、TabControl

2023-09-02 01:33:56 作者:我希望嫁给爱情

因此​​,这里的问题。我有一个窗口分为三个小组。中间包含图画表面和左侧包含选项卡控件。该标签控件的标签吃掉均包含按钮,必须在右侧面板中打开新菜单的列表中。我无法弄清楚如何做到这一点的code,所以我使出单独创建每个按钮,在C#中的运行时间。好像必须有一个更好的方式去了解它。目前,我叫下面的功能键点击事件得出不同菜单的名为tabctrl右面板在运行时的TabControl。它需要一个字符串参数来指定哪些套餐的画,虽然在这一点上我只写了$ C $下一个菜单的。下面是code的功能和XML。有没有更好的方法去吗?

XML:

 < TabControl的DockPanel.Dock =右背景=白色X:名称=tabctrl>
        < TabItem的身高=38NAME =TAB1标题=TAB3/>
    < / TabControl的>
 

C#:

 私人无效menuOpen(字符串menuSelected)
    {

        //什么菜单被打开逻辑语句
        开关(menu​​Selected)
        {
            案背景:
                {
                    //删除当前标签


                    //初始化标签项目,设置标题和标签项添加到标签控件
                    TabItem的背景=新的TabItem();
                    BackGround.Header =背景;
                    tabctrl.Items.Insert(1,背景);
                    BackGround.Height = 38;

                    //初始化协议栈面板,设置方向,并添加标签控件
                    StackPanel的面板=新的StackPanel();
                    panel.Orientation = Orientation.Vertical;
                    BackGround.Content =面板;

                    //初始化菜单项
                    按钮AddMap =新按钮();
                    按钮AddDemoMap =新按钮();
                    按钮RemoveMap =新按钮();
                    按钮MoveSelected =新按钮();
                    按钮属性=新的Button();
                    按钮ScaleBackground =新按钮();

                    //定义按钮文本
                    AddMap.Content =添加地图;
                    AddDemoMap.Content =添加演示图;
                    RemoveMap.Content =删除地图;
                    MoveSelected.Content =移动选定的地图列表顶部;
                    Properties.Content =属性;
                    ScaleBackground.Content =尺度背景来管;

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

                    //将按钮添加到的StackPanel
                    panel.Children.Add(AddMap);
                    panel.Children.Add(AddDemoMap);
                    panel.Children.Add(RemoveMap);
                    panel.Children.Add(MoveSelected);
                    panel.Children.Add(属性);
                    panel.Children.Add(ScaleBackground);
                }
                打破;
 

解决方案

好吧......让我们看看:

首先,你必须学会​​去思考你的UI中的摘要办法:

  

什么是TabControl的?

这是小部件的列表,用户可以在同一时间1个活动部件的图形重新presentation。这些小部件有一个标题(标签项目文本),一个可见性状态,以及启用/禁用状态。

  

什么是一堆堆叠按钮? (工具栏,如果你要称呼它)

这是的,用户可以在任何给定的时间执行的操作列表的图形重新presentation。这些行动有一个说明(按钮的内容),可能是一个相关的图标或图形图像,和启用/禁用状态。

  

什么是文本菜单或菜单?

与上面相同,它的操作,该用户可以执行的列表的图形重新presentation

  

我会如何在WPF创建动态的TabControl?

wpf怎样动态绑定TabControl的多个TabItem

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

 <窗​​口x:类=WpfApplication4.Window12
        的xmlns =htt​​p://schemas.microsoft.com/winfx/2006/xaml/$p$psentation
        的xmlns:X =htt​​p://schemas.microsoft.com/winfx/2006/xaml
        标题=Window12高度=300宽度=300>
    < Window.Resources>
        < BooleanToVisibilityConverter X:关键=BoolToVisibilityConverter/>
    < /Window.Resources>
        <的TabControl的ItemsSource ={绑定表项}的SelectedItem ={结合的SelectedItem}>
            < TabControl.ItemContainerStyle>
                <风格的TargetType =TabItem的>
                    < setter属性=IsEnabled的VALUE ={结合的IsEnabled}/>
                    < setter属性=能见度VALUE ={结合可见性,转换器= {的StaticResource BoolToVisibilityConverter}}/>
                    < setter属性=头值={结合标题}/>
                < /样式和GT;
            < /TabControl.ItemContainerStyle>
        < / TabControl的>
< /窗>
 

视图模型:

 公共类TabbedViewModel:ViewModelBase
    {
        私人的ObservableCollection< TabViewModel> _items;
        公众的ObservableCollection< TabViewModel>项目
        {
            {返回_items? (_items =新的ObservableCollection< TabViewModel>()); }
        }

        私人ViewModelBase _selectedItem;
        公共ViewModelBase的SelectedItem
        {
            {返回_selectedItem; }
            组
            {
                _selectedItem =价值;
                NotifyPropertyChange(()=>的SelectedItem);
            }
        }
    }

    公共类TabViewModel:ViewModelBase
    {
        私人字符串_title;
        公共字符串标题
        {
            {返回_title; }
            组
            {
                _title =价值;
                NotifyPropertyChange(()=>标题);
            }
        }

        私人布尔_isEnabled;
        公共BOOL的IsEnabled
        {
            {返回_isEnabled; }
            组
            {
                _isEnabled =价值;
                NotifyPropertyChange(()=>的IsEnabled);
            }
        }

        私人布尔_isVisible;
        公共BOOL ISVISIBLE
        {
            {返回_isVisible; }
            组
            {
                _isVisible =价值;
                NotifyPropertyChange(()=>可见性);
            }
        }
    }
 

通过本实施例,在TabControl的每个项目(TabItem的)将被绑定到的ViewModels之一,那么它的继承基TabViewModel为每个标签页并创建适当的只是一个问题的DataTemplate 每个

正如你在这个例子看,我绝不创建或操纵在code任何用户界面元素。这简化Ç很多都$ C $,并有助于保持逻辑和UI之间有明确的区分。 您可以应用同样的概念,一切都在上头。

So here's the issue. I have a window divided into three panels. The middle contains a drawing surface and the left contains a tab control. The tab control's tab eats each consist of a list of buttons that must open new menu's in the right panel. I can't figure out how to do this in code so I resorted to individually creating each button at run time in C#. Seems like there has to be a better way to go about it. I currently call the below function for button click events to draw different menu's in the TabControl named "tabctrl" right panel at runtime. It takes a string argument to specify what set of menus to draw, although at this point I've only written the code for one the menu's. Below is the code for the function and the xml. Is there a better way to go about this?

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;

解决方案

Ok... lets see:

First of all, you must learn to think your UI in an abstract way:

What is a TabControl?

It's a graphical representation of a List of widgets, where the user can have 1 active widget at a time. These widgets have a Title (the tab item text), a Visibility state, and an Enabled/Disabled state.

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

It's a graphical representation of a List of actions that the user can perform at any given time. These actions have a Description (the button's content), possibly an associated icon or graphical image, and an Enabled / Disabled State.

What is a ContextMenu, or a Menu?

The same as above, it's a graphical representation of a list of Actions that the user can perform.

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

This is the XAML for a WPF TabControl that supports dynamic Children:

<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>

ViewModel:

 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);
            }
        }
    }

With this example, each item (TabItem) in the TabControl will be bound to one of the ViewModels, then it's just a matter of inheriting the base TabViewModel for each of your tabs and creating a proper DataTemplate for each.

As you can see in this example, I'm in no way creating or manipulating ANY UI elements in code. This simplifies all code A LOT, and helps maintain a clear separation between logic and UI. You can apply this same concept to everything in WPF.