基于子项的IsChecked在TabControl中隐藏/显示网格

时间:2014-12-08 13:11:52

标签: wpf triggers tabcontrol ribbon

我试图制作自己的TabControl,这是Style的一部分:

<Style TargetType="TabControl">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TabControl}">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                            <RowDefinition Height="*"/>
                    </Grid.RowDefinitions>

                    <TabPanel Grid.Row="0" Panel.ZIndex="1" Margin="0,0,4,-1" IsItemsHost="True" Background="Transparent" />

                    <Border Name="ContentBorder" Grid.Row="1" BorderBrush="#FFD4D4D4" BorderThickness="1" Visibility="{Binding IsChecked, ElementName=HideGrid, Converter={StaticResource Bool2VisibilityConverter}}">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="100*"/>
                                    <ColumnDefinition Width="Auto"/>
                            </Grid.ColumnDefinitions>
                            <ContentPresenter ContentSource="SelectedContent" />
                        </Grid>
                    </Border>

                    <ToggleButton IsChecked="True" Name="HideGrid" Content="Hide" Grid.Row="1" Margin="722,73,0,0" HorizontalAlignment="Right" VerticalAlignment="Bottom" Visibility="{Binding IsChecked, ElementName=HideGrid, Converter={StaticResource Bool2VisibilityConverter}}"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style TargetType="TabItem">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="TabItem">
                <Grid Name="Item">
                    <Border Name="ItemBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1,1,1,0">
                        <ContentPresenter x:Name="ContentSite"
                           VerticalAlignment="Center"
                            HorizontalAlignment="Center"
                            ContentSource="Header"
                            Margin="10,3"/>
                     </Border>
                </Grid>
                <ControlTemplate.Triggers>
                   <Trigger Property="IsSelected" Value="True">
                        <Setter TargetName="ItemBorder" Property="BorderBrush" Value="#FFD4D4D4" />
                        <Setter TargetName="ItemBorder" Property="Background" Value="White"/>
                        <Setter Property="Foreground" Value="#FF2B579A"/>
                    </Trigger>
                    <Trigger Property="IsSelected" Value="False">
                        <Setter TargetName="ItemBorder" Property="BorderThickness" Value="0,0,0,1"/>
                    </Trigger>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Foreground" Value="#FF2B579A"/>                        </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>

    <Setter Property="BorderBrush" Value="Transparent"/>
    <Setter Property="OverridesDefaultStyle" Value="True"/>
</Style>

此样式(暂时),如下所示:忽略ToggleButton的样式:)

Ignore the style of the ToggleButton

基本上,我尝试做的是模仿Office / Windows 8功能区:

  1. 点击Button,取消选中任何标签,隐藏网格和ToggleButton
  2. 点击TabPanel,显示网格和Button
  3. 我能做什么:

    1. 点击ToggleButton
    2. 隐藏网格和ToggleButton

      GIF!

      问题:

      选择一个check后,我如何ToggleButton TabItem?  检查unselect后,我怎样才能TabItems ToggleButton

      工作解决方案

      我只需要创建一个自定义的TabControl类:

      public class HideableTabControl : TabControl
      {
          #region Variables
      
          private Button _button;
          private TabPanel _tabPanel;
          private Border _border;
      
          #endregion
      
          static HideableTabControl()
          {
              DefaultStyleKeyProperty.OverrideMetadata(typeof(HideableTabControl), new FrameworkPropertyMetadata(typeof(HideableTabControl)));
          }
      
          public override void OnApplyTemplate()
          {
              base.OnApplyTemplate();
      
              _button = Template.FindName("HideGrid", this) as Button;
              _tabPanel = Template.FindName("TabPanel", this) as TabPanel;
              _border = Template.FindName("ContentBorder", this) as Border;
      
              if (_button != null)
                  _button.PreviewMouseDown += Button_Clicked;
      
              if (_tabPanel != null)
                  foreach (TabItem tabItem in _tabPanel.Children)
                  {
                      tabItem.PreviewMouseDown += TabItem_PreviewMouseDown;
                  }
          }
      
          private void TabItem_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
          {
              var selected = sender as TabItem;
      
              if (selected != null)
                  selected.IsSelected = true;
      
              _button.Visibility = Visibility.Visible;
              _border.Visibility = Visibility.Visible;
          }
      
          private void Button_Clicked(object sender, System.Windows.Input.MouseButtonEventArgs e)
          {
              foreach (TabItem child in _tabPanel.Children)
              {
                  child.IsSelected = false;
              }
      
              _border.Visibility = Visibility.Collapsed;
              _button.Visibility = Visibility.Collapsed;
          }
      }
      

      这种简单的风格:

      <Style TargetType="{x:Type local:HideableTabControl}">
          <Setter Property="Template">
              <Setter.Value>
                  <ControlTemplate TargetType="{x:Type local:HideableTabControl}">
                      <Grid>
                          <Grid.RowDefinitions>
                              <RowDefinition Height="Auto"/>
                              <RowDefinition Height="*"/>
                          </Grid.RowDefinitions>
                          <TabPanel Name="TabPanel"  Grid.Row="0" Panel.ZIndex="1" Margin="5,0,0,-1" IsItemsHost="True" Background="Transparent"/>
                          <Border Name="ContentBorder" Grid.Row="1" BorderBrush="#FFD4D4D4" BorderThickness="0,1" >
                              <ContentPresenter ContentSource="SelectedContent"/> 
                          </Border>
                          <Button Name="HideGrid" Content="^ " Grid.Row="1" HorizontalAlignment="Right" VerticalAlignment="Bottom" Style="{DynamicResource OfficeButtonStyle}"/>
                      </Grid>
                  </ControlTemplate>
              </Setter.Value>
          </Setter>
      </Style>
      

      结果如下:

      I Did It!

2 个答案:

答案 0 :(得分:1)

试试这种风格:

<Style TargetType="TabControl">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type TabControl}">
                <Grid>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="*"/>
                    </Grid.RowDefinitions>

                    <ToggleButton IsChecked="True" x:Name="tabPanelHeader" Grid.Row="0" OverridesDefaultStyle="True"  Panel.ZIndex="1" Margin="0,0,4,-1" >
                        <TabPanel x:Name="tabPanel" Background="Transparent" IsItemsHost="True"  />
                        <ToggleButton.Template>
                            <ControlTemplate TargetType="ToggleButton">
                                        <ContentPresenter>
                                        </ContentPresenter>
                            </ControlTemplate>
                        </ToggleButton.Template>
                    </ToggleButton>

                    <Border Name="ContentBorder" Grid.Row="1" BorderBrush="#FFD4D4D4" BorderThickness="1" Visibility="{Binding IsChecked, ElementName=tabPanelHeader, Converter={StaticResource Bool2VisibilityConverter}}" >
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition Width="100*"/>
                                <ColumnDefinition Width="Auto"/>
                            </Grid.ColumnDefinitions>
                            <ContentPresenter ContentSource="SelectedContent" />
                        </Grid>
                    </Border>
                    <ToggleButton IsChecked="{Binding IsChecked,ElementName=tabPanelHeader}" Name="HideGrid" Content="Hide" Grid.Row="1" HorizontalAlignment="Right" VerticalAlignment="Bottom" Visibility="{Binding IsChecked, ElementName=tabPanelHeader, Converter={StaticResource Bool2VisibilityConverter}}"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

答案 1 :(得分:1)

我尝试使用MVVM pattern

找到解决方案

尝试以下方法:

查看:

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:wpfApplication1="clr-namespace:WpfApplication1"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <wpfApplication1:ViewModel/>
    </Window.DataContext>

    <Window.Resources>

        <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
        <Style TargetType="TabControl">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type TabControl}">
                        <Grid>
                            <Grid.RowDefinitions>
                                <RowDefinition Height="Auto"/>
                                <RowDefinition Height="*"/>
                            </Grid.RowDefinitions>

                            <TabPanel Grid.Row="0" Panel.ZIndex="1" Margin="0,0,4,-1" IsItemsHost="True" Background="Transparent" />

                            <Border Name="ContentBorder" Grid.Row="1" BorderBrush="#FFD4D4D4" BorderThickness="1" Visibility="{Binding IsChecked, ElementName=HideGrid, Converter={StaticResource BooleanToVisibilityConverter}}">
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="100*"/>
                                        <ColumnDefinition Width="Auto"/>
                                    </Grid.ColumnDefinitions>
                                    <ContentPresenter ContentSource="SelectedContent" />
                                </Grid>
                            </Border>

                            <ToggleButton 
                                Command="{Binding Path=UnselectAllTabsCommand}"
                                IsChecked="{Binding Path=IsHideButtonChecked, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Name="HideGrid" Content="Hide" Grid.Row="1" Margin="722,73,0,0" HorizontalAlignment="Right" VerticalAlignment="Bottom" Visibility="{Binding Path=IsHideButtonChecked, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource BooleanToVisibilityConverter}}"/>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

        <Style TargetType="TabItem">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="TabItem">
                        <Grid Name="Item">
                            <Border Name="ItemBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="1,1,1,0">
                                <ContentPresenter x:Name="ContentSite"
                           VerticalAlignment="Center"
                            HorizontalAlignment="Center"
                            ContentSource="Header"
                            Margin="10,3"/>
                            </Border>
                        </Grid>
                        <ControlTemplate.Triggers>
                            <Trigger Property="IsSelected" Value="True">
                                <Setter TargetName="ItemBorder" Property="BorderBrush" Value="#FFD4D4D4" />
                                <Setter TargetName="ItemBorder" Property="Background" Value="White"/>
                                <Setter Property="Foreground" Value="#FF2B579A"/>
                            </Trigger>
                            <Trigger Property="IsSelected" Value="False">
                                <Setter TargetName="ItemBorder" Property="BorderThickness" Value="0,0,0,1"/>
                            </Trigger>
                            <Trigger Property="IsMouseOver" Value="True">
                                <Setter Property="Foreground" Value="#FF2B579A"/>
                            </Trigger>
                        </ControlTemplate.Triggers>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>

            <Setter Property="BorderBrush" Value="Transparent"/>
            <Setter Property="OverridesDefaultStyle" Value="True"/>
        </Style>

    </Window.Resources>

    <Grid>
        <TabControl SelectedItem="{Binding Path=SelectedItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="SelectionChanged">
                    <i:InvokeCommandAction Command="{Binding Path=ShowHideButtonCommand}"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
            <TabControl.Items>
                <TabItem Header="Tab 1"  />
                <TabItem Header="Tab 2" />
                <TabItem Header="Tab 3" />
            </TabControl.Items>
        </TabControl>
    </Grid>
</Window>

视图模型:

namespace WpfApplication1
{
    using System;
    using System.ComponentModel;
    using System.Runtime.CompilerServices;
    using System.Windows.Input;

    /// <summary>
    ///     The view model.
    /// </summary>
    internal class ViewModel : INotifyPropertyChanged
    {
        #region Fields

        /// <summary>
        ///     Check if is hide button checked
        /// </summary>
        private bool isHideButtonChecked = true;

        /// <summary>
        ///     The selected item
        /// </summary>
        private object selectedItem;

        #endregion

        #region Public Events

        /// <summary>
        ///     The property changed.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        #region Public Properties

        /// <summary>
        ///     Gets or sets a value indicating whether this instance is hide button checked.
        /// </summary>
        /// <value>
        ///     <c>true</c> if this instance is hide button checked; otherwise, <c>false</c>.
        /// </value>
        public bool IsHideButtonChecked
        {
            get
            {
                return this.isHideButtonChecked;
            }

            set
            {
                this.isHideButtonChecked = value;
                this.OnPropertyChanged();
            }
        }

        /// <summary>
        ///     Gets or sets the selected item.
        /// </summary>
        /// <value>
        ///     The selected item.
        /// </value>
        public object SelectedItem
        {
            get
            {
                return this.selectedItem;
            }

            set
            {
                this.selectedItem = value;
                this.OnPropertyChanged();
            }
        }

        /// <summary>
        ///     Gets the show hide button command.
        /// </summary>
        /// <value>
        ///     The show hide button command.
        /// </value>
        public ICommand ShowHideButtonCommand
        {
            get
            {
                return new CommandHandler(
                    () =>
                        {
                            if (this.SelectedItem != null)
                            {
                                this.IsHideButtonChecked = true;
                            }
                        });
            }
        }

        /// <summary>
        /// Gets the unselect all tabs command.
        /// </summary>
        public ICommand UnselectAllTabsCommand
        {
            get
            {
                return new CommandHandler(() => { this.SelectedItem = null; });
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// The on property changed.
        /// </summary>
        /// <param name="propertyName">
        /// The property name.
        /// </param>
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChangedEventHandler handler = this.PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #endregion
    }

    /// <summary>
    /// The command handler.
    /// </summary>
    public class CommandHandler : ICommand
    {
        #region Fields

        /// <summary>
        /// The _action.
        /// </summary>
        private readonly Action _action;

        /// <summary>
        /// The _can execute.
        /// </summary>
        private readonly bool _canExecute;

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="CommandHandler"/> class.
        /// </summary>
        /// <param name="action">
        /// The action.
        /// </param>
        /// <param name="canExecute">
        /// The can execute.
        /// </param>
        public CommandHandler(Action action, bool canExecute)
        {
            this._action = action;
            this._canExecute = canExecute;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="CommandHandler"/> class.
        /// </summary>
        /// <param name="action">
        /// The action.
        /// </param>
        public CommandHandler(Action action)
            : this(action, true)
        {
        }

        #endregion

        #region Public Events

        /// <summary>
        /// The can execute changed.
        /// </summary>
        public event EventHandler CanExecuteChanged;

        #endregion

        #region Public Methods and Operators

        /// <summary>
        /// The can execute.
        /// </summary>
        /// <param name="parameter">
        /// The parameter.
        /// </param>
        /// <returns>
        /// The <see cref="bool"/>.
        /// </returns>
        public bool CanExecute(object parameter)
        {
            return this._canExecute;
        }

        /// <summary>
        /// The execute.
        /// </summary>
        /// <param name="parameter">
        /// The parameter.
        /// </param>
        public void Execute(object parameter)
        {
            this._action();
        }

        #endregion
    }
}

注:

  

请注意,您需要在项目中引用程序集:System.Windows.Interactivity,以便在引发tabControl selectionChanged事件时调用命令操作。

上面的代码已经过测试并且对我正常工作(see this screen recording in flash video)。

请尝试一下,让我知道。

我希望能帮到你。