【问题标题】:How to create WPF user control: custom TabItem?如何创建 WPF 用户控件:自定义 TabItem?
【发布时间】:2019-07-28 20:24:07
【问题描述】:

提前感谢您的支持!我正在尝试创建一个自定义选项卡项来充当动态创建 UI 元素的画布。这是一张图片,可以让我了解我想要在这个自定义控件中做什么:

我需要能够在父表单中为 TabControl 动态生成选项卡项 - 问题是我的代码似乎对 TabItem 没有任何作用 - 它始终是空白的,它不会抱怨我的代码。少了什么东西?感谢您的帮助!

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

设计师:

【问题讨论】:

  • 我不在 WPF 中使用自定义控件。我使用的是类型定位数据模板。在 WPF 中调整用户控件非常困难,但可以轻松复制和修改数据模板。
  • 有趣 - 你能提供一个资源,也许是正确使用的视频?
  • 我确实写了一篇关于 MVVM 的旧介绍,这是您应该与 WPF 一起使用的模式。它还处理数据模板。 social.msdn.microsoft.com/Forums/vstudio/en-US/…
  • 您需要将 TabItem 放在 TabControl 中。

标签: c# wpf xaml


【解决方案1】:

在 WPF 中,如果你想动态创建控件,你总是必须使用模板。 TabControlItemsControlTabItem 元素(选项卡)是为ItemsControl.ItemsSource 集合中的每个项目自动生成的。这个TabItem 的视觉可以使用样式和模板来设计。
使用TabControl.ContentTemplate 属性为每个选项卡的内容指定DataTemplate

首先,您必须创建应在TabItem 中显示的数据模型。

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

然后创建一个视图模型来处理选项卡数据并公开TabControl 的项目源。
视图模型是TabControlDataContext

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 可以从 ICommand(例如点击按钮)或某些事件(例如可用的新数据)调用。

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>

【讨论】:

  • 这是一个很棒的解释,让我走上了正确的道路。谢谢。
  • 如何在动态添加的 TabItem 中添加像“{DynamicResource TabItemStyle}”这样的自定义样式?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多