简体   繁体   English

如何创建WPF用户控件:自定义TabItem?

[英]How to create WPF user control: custom TabItem?

Thanks in advance for any support! 预先感谢您的支持! I am trying to create a custom tab item to act as a canvas for dynamically creating UI elements. 我正在尝试创建一个自定义选项卡项,以充当动态创建UI元素的画布。 Here is an image to give an idea as to what I would like in this custom control: 这是一张有关此自定义控件中所需内容的图片: TabItem模板

I need to be able to generate the Tab Items dynamically to the TabControl in a parent form - the problem is that my code seems to do nothing to the TabItem - it's just always blank and it doesn't complain about my code. 我需要能够以父级形式动态生成TabControl的Tab项-问题是我的代码似乎对TabItem没有任何作用-它始终是空白的,并且不会抱怨我的代码。 What's missing? 缺少了什么? Thanks for any help! 谢谢你的帮助!

My WPF user control tabitem Code: 我的WPF用户控件Tabitem代码:

<UserControl x:Class="Configuration_Manager.SearchTab"
             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:Configuration_Manager"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">

    <TabItem Header="Search Configuration Name">
        <StackPanel>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>
                <GroupBox Header="Git Repo Credentials:">
                    <StackPanel>
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*" />
                                <ColumnDefinition Width="3*" />
                            </Grid.ColumnDefinitions>
                            <Label Grid.Column="0" Content="Server Address:" />
                            <TextBox Grid.Column="1" Margin="2" />
                        </Grid>
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*" />
                                <ColumnDefinition Width="3*" />
                            </Grid.ColumnDefinitions>
                            <Label Grid.Column="0" Content="Username:" />
                            <TextBox Grid.Column="1" Margin="2" />
                        </Grid>
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*" />
                                <ColumnDefinition Width="3*" />
                            </Grid.ColumnDefinitions>
                            <Label Grid.Column="0" Content="Password:" />
                            <TextBox Grid.Column="1" Margin="2" />
                        </Grid>
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="*" />
                                <ColumnDefinition Width="2*" />
                                <ColumnDefinition Width="*" />
                            </Grid.ColumnDefinitions>
                            <CheckBox x:Name="CheckBoxStoreCredentials" Content="Store Credentials" Grid.Column="0" IsChecked="False" VerticalAlignment="Center"/>
                            <Button x:Name="ButtonDownloadConfiguration"  Content="Download Configuration" Grid.Column="2" Margin="5" />
                        </Grid>
                    </StackPanel>
                </GroupBox>
            </Grid>
        </StackPanel>
    </TabItem>
</UserControl>

The Designer: 设计师: 标签项目

In WPF if you want to dynamically create controls you always have to use templates. 在WPF中,如果要动态创建控件,则必须始终使用模板。 TabControl is an ItemsControl . TabControlItemsControl TabItem elements (the tabs) are automatically generated for each item inside the ItemsControl.ItemsSource collection. TabItem元素(选项卡)是为ItemsControl.ItemsSource集合内的每个项目自动生成的。 The visual of this TabItem can be designed by using styles and templates. 可以使用样式和模板来设计此TabItem的外观。
Use the TabControl.ContentTemplate property to specify the DataTemplate for the content of each tab 使用TabControl.ContentTemplate属性为每个选项卡的内容指定DataTemplate

First you have to create the data model that should be displayed inside a TabItem . 首先,您必须创建应在TabItem内部显示的数据模型。

TabData.cs: TabData.cs:

public class TabData : INotifyPropertyChanged
{
  public TabData(string header)
  {
    this.Header = header;
  }

  public string Header { get; set; }

  private string serverAddress;
  public string ServerAddress
  {
    get => this.serverAddress;
    set
    {
      if (value == this.serverAddress) return;
      this.serverAddress = value;
      OnPropertyChanged();
    }
  }

  private string username;
  public string Username
  {
    get => this.username;
    set
    {
      if (value == this.username) return;
      this.username = value;
      OnPropertyChanged();
    }
  }

  private string password;
  public string Password
  {
    get => this.password;
    set
    {
      if (value == this.password) return;
      this.password = value;
      OnPropertyChanged();
    }
  }

  public event PropertyChangedEventHandler PropertyChanged;    
  protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
  {
    this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  }
}

Then create a view model that handles the tab data and exposes the items source for the TabControl . 然后创建一个处理选项卡数据的视图模型,并公开TabControl的项目源。
The view model is the DataContext of the TabControl . 视图模型是TabControlDataContext

ViewModel.cs ViewModel.cs

public class ViewModel: INotifyPropertyChanged
{
  public ViewModel()
  {
    this.TabDatas = new ObservableCollection<TabData>()
    {
      new TabData("First Tab"),
      new TabData("Second Tab"),
      new TabData("Third Tab")
    };
  }

  // Adding a new TabData item to the TabDatas collection 
  // will dynamically create a new TabItem inside the TabControl
  public void AddNewTab()
  {
    this.TabDatas.Add(new TabData("Fourth Tab"));
  }


  public ObservableCollection<TabData> TabDatas { get; set; }

  public event PropertyChangedEventHandler PropertyChanged;    
  protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
  {
    this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
  }
}

AddNewTab can be invoked from a ICommand (eg on button clicked) or some event (eg new data available). 可以从ICommand (例如单击按钮)或某个事件(例如可用的新数据)中调用AddNewTab

MainWindow.xaml: MainWindow.xaml:

<Window>
  <Window.DataContext>
    <ViewModel />
  </Window.DataContext>

  <Grid>

    <!-- Use DisplayMemberPath property to set the source property for the tab header -->
    <TabControl x:Name="TabControl" 
                ItemsSource="{Binding TabDatas}" 
                DisplayMemberPath="Header" >

      <!-- Use a DataTemplate to design the visual appearance of the TabItem content -->
      <TabControl.ContentTemplate>
        <DataTemplate DataType="TabData">
          <StackPanel>
            <Grid>
              <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
              </Grid.ColumnDefinitions>
              <GroupBox Header="Git Repo Credentials:">
                <StackPanel>
                  <Grid>
                    <Grid.ColumnDefinitions>
                      <ColumnDefinition Width="*" />
                      <ColumnDefinition Width="3*" />
                    </Grid.ColumnDefinitions>
                    <Label Grid.Column="0"
                           Content="Server Address:" />
                    <TextBox Grid.Column="1"
                             Margin="2" 
                             Text="{Binding ServerAddress}" />
                  </Grid>
                  <Grid>
                    <Grid.ColumnDefinitions>
                      <ColumnDefinition Width="*" />
                      <ColumnDefinition Width="3*" />
                    </Grid.ColumnDefinitions>
                    <Label Grid.Column="0"
                           Content="Username:" />
                    <TextBox Grid.Column="1"
                             Margin="2"
                             Text="{Binding Username}"/>
                  </Grid>
                  <Grid>
                    <Grid.ColumnDefinitions>
                      <ColumnDefinition Width="*" />
                      <ColumnDefinition Width="3*" />
                    </Grid.ColumnDefinitions>
                    <Label Grid.Column="0"
                           Content="Password:" />
                    <TextBox Grid.Column="1"
                             Margin="2"
                             Text="{Binding Password}"/>
                  </Grid>
                  <Grid>
                    <Grid.ColumnDefinitions>
                      <ColumnDefinition Width="*" />
                      <ColumnDefinition Width="2*" />
                      <ColumnDefinition Width="*" />
                    </Grid.ColumnDefinitions>
                    <CheckBox x:Name="CheckBoxStoreCredentials"
                              Content="Store Credentials"
                              Grid.Column="0"
                              IsChecked="False"
                              VerticalAlignment="Center" />
                    <Button x:Name="ButtonDownloadConfiguration"
                            Content="Download Configuration"
                            Grid.Column="2"
                            Margin="5" />
                  </Grid>
                </StackPanel>
              </GroupBox>
            </Grid>
          </StackPanel>
        </DataTemplate>
      </TabControl.ContentTemplate>
    </TabControl>
  </Grid>
</Window>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM