Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
97 views
in Technique[技术] by (71.8m points)

c# - Dynamically Updating TabControl Content at Runtime

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;
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...