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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_34047402

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值