5.0.7 TabControl的使用
本文使用4个例子介绍TabControl的使用。包括xaml以及C#代码生成TabControl.其中第4个例子是使用TabControl来实现IO监控,作为工控软件的一部分。
【例1】使用TabControl以及 TabItem实现简单功能:
注意:TabControl的属性 TabStripPlacement可以对选项卡索引放置位置进行设置(上下左右)
<TabControl Margin="5" TabStripPlacement="Right"><TabItem Header="Tab One"><StackPanel Margin="5" ><TextBlock>这是Tab 1</TextBlock><CheckBox>选项1</CheckBox><CheckBox>选项2</CheckBox><CheckBox>选项3</CheckBox></StackPanel></TabItem><TabItem Header="Tab two"><StackPanel ><TextBlock>这是Tab 2</TextBlock></StackPanel></TabItem></TabControl>
【例2】代码生成
选项卡1中:通过建立一个StackPanel(其中添加文本以及按钮);然后设置为TabItem1的Content。
public Window3(){InitializeComponent();TabItem newTab1 = new TabItem();newTab1.Header = "新选项卡1";StackPanel stackpanel = new StackPanel() ;stackpanel.Orientation = Orientation.Vertical;stackpanel.Children.Add(new TextBlock { Text = "动态添加的页面1内容" });stackpanel.Children.Add(new System.Windows.Controls.Button { Content = "按钮" });newTab1.Content = stackpanel;this.MyTab.Items.Add(newTab1); TabItem newTab2 = new TabItem();newTab2.Header = "新选项卡2";newTab2.Content = new TextBlock { Text = "动态添加的页面2内容" };this.MyTab.Items.Add(newTab2);// 选择最后一个选项卡MyTab.SelectedIndex = MyTab.Items.Count - 1;this.DataContext = new MainViewModel3();}
【例3】使用MVVM进行绑定
<Window x:Class="WpfApp1.Window3"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.com/expression/blend/2008"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"xmlns:local="clr-namespace:WpfApp1"mc:Ignorable="d"Title="Window3" Height="450" Width="800"><TabControl Margin="5" TabStripPlacement="Top" Name="MyTab"ItemsSource="{Binding Tabs}" SelectedItem="{Binding SelectedTab}"><TabControl.ItemTemplate><DataTemplate><TextBlock Text="{Binding Header}"/></DataTemplate> </TabControl.ItemTemplate><TabControl.ContentTemplate><DataTemplate><TextBlock Text="{Binding Content}"/></DataTemplate></TabControl.ContentTemplate></TabControl>
</Window>
public class TabItemModel{public string Header { get; set; }public string Content { get; set; }}public class MainViewModel3{public ObservableCollection<TabItemModel> Tabs { get; } = new ObservableCollection<TabItemModel>();public TabItemModel SelectedTab { get; set; }public MainViewModel3(){Tabs.Add(new TabItemModel { Header = "第一页", Content = "内容1" });Tabs.Add(new TabItemModel { Header = "第二页", Content = "内容2" });SelectedTab = Tabs[1];}}
【例4】PLC的IO监控界面
本文使用Uni
<UserControl x:Class="WpfApp1.windowIO"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:WpfApp1"xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"Background="#fafafa"><Grid Margin="10"><Grid.RowDefinitions><RowDefinition Height="Auto"/><RowDefinition Height="*"/><RowDefinition Height="Auto"/></Grid.RowDefinitions><!-- 模式切换 --><StackPanel Orientation="Horizontal" HorizontalAlignment="Center"><RadioButton x:Name="rbInputs" Content="全输入" GroupName="Mode" Margin="5" IsChecked="True" Checked="rbInputs_Checked" /><RadioButton x:Name="rbOutputs" Content="全输出" GroupName="Mode" Margin="5" Checked="rbOutputs_Checked"/></StackPanel><!-- 分页内容 --><TabControl Grid.Row="1" x:Name="PagesTab" Background="Transparent" BorderThickness="0"><TabControl.ItemContainerStyle><Style TargetType="TabItem"><Setter Property="Visibility" Value="Collapsed"/><!-- 隐藏Tab头 --></Style></TabControl.ItemContainerStyle></TabControl><!-- 翻页导航 --><StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Center"><Button Content="上一页" Click="PrevPage_Click" Style="{StaticResource MaterialDesignFlatButton}"/><TextBlock Text="{Binding CurrentPage}" Margin="10,0" VerticalAlignment="Center"/><Button Content="下一页" Click="NextPage_Click" Style="{StaticResource MaterialDesignFlatButton}"/></StackPanel></Grid>
</UserControl>
public partial class windowIO : UserControl{private windowIOModel _viewModel = new windowIOModel();private int _itemsPerPage = 32; // private int totalPages = 0;public bool bInitialized = false;public windowIO(){InitializeComponent();this.DataContext = _viewModel;UpdatePageContent();bInitialized = true;}private void UpdatePageContent(){PagesTab.Items.Clear();if (this.rbOutputs.IsChecked==true){totalPages = (_viewModel.Outputs.Count + _itemsPerPage - 1) / _itemsPerPage;}else{totalPages = (_viewModel.Inputs.Count + _itemsPerPage - 1) / _itemsPerPage;}for (int page = 0; page < totalPages; page++){var pageContent = new TabItem();var grid = new UniformGrid() { Columns = 2, Margin = new Thickness(10) };var UniformGrid_left = new UniformGrid() { Columns = 1 };var UniformGrid_right = new UniformGrid() { Columns = 1 };int i = 0;if (rbInputs.IsChecked == true){// 全输入模式foreach (var input in _viewModel.Inputs.Skip(page * 32).Take(32)){if(i<16){UniformGrid_left.Children.Add(new SingleIOMonitor{DataContext = input//IsActive = input.IsActive});}else{UniformGrid_right.Children.Add(new SingleIOMonitor{DataContext = input//IsActive = input.IsActive});};i++;} }else{// 全输入模式foreach (var output in _viewModel.Outputs.Skip(page * 32).Take(32)){if (i < 16){UniformGrid_left.Children.Add(new SingleIOMonitor{DataContext = output});}else{UniformGrid_right.Children.Add(new SingleIOMonitor{DataContext = output});}i++;}}grid.Children.Add(UniformGrid_left);grid.Children.Add(UniformGrid_right);pageContent.Content = grid;PagesTab.Items.Add(pageContent);}PagesTab.SelectedIndex = _viewModel.CurrentPage=0;}private void PrevPage_Click(object sender, RoutedEventArgs e){if (_viewModel.CurrentPage > 0){_viewModel.CurrentPage--;PagesTab.SelectedIndex = _viewModel.CurrentPage;} }private void NextPage_Click(object sender, RoutedEventArgs e){if (_viewModel.CurrentPage < totalPages){_viewModel.CurrentPage++;PagesTab.SelectedIndex = _viewModel.CurrentPage;} }private void rbInputs_Checked(object sender, RoutedEventArgs e){if(bInitialized==true){UpdatePageContent();} }private void rbOutputs_Checked(object sender, RoutedEventArgs e){if (bInitialized == true){UpdatePageContent();} }}
/// <summary>/// IO 标签类/// </summary>public class IOLabel : ObservableObject, IComparable<IOLabel>{public int index; //在byte数组中的序号public string Address { get; set; } //地址public string Comment { get; set; } //注释/// <summary>/// Value数值,即IO/// </summary>private bool _Value;public bool Value{get => _Value;set { SetProperty(ref _Value, value);}}public int CompareTo(IOLabel other){if (other == null) return 1; // null视为最小return index.CompareTo(other.index); // 使用int的CompareTo方法}}public class windowIOModel : ObservableObject{public ObservableCollection<IOLabel> Inputs { get; } = new ObservableCollection<IOLabel>();public ObservableCollection<IOLabel> Outputs { get; } = new ObservableCollection<IOLabel>();public BytesArrayTag inputTags;public BytesArrayTag OutputTags;private int _currentPage;public int CurrentPage{get => _currentPage;set { SetProperty(ref _currentPage, value); }}
}