2013-10-11 101 views
2

我有一個TabItem綁定到按鈕能見度

<Style x:Key="SubStudioTabItem" TargetType="{x:Type TabItem}"> 
    <Setter Property="FocusVisualStyle" Value="{x:Null}"/> 
    <Setter Property="Background" Value="Transparent"/> 
    <Setter Property="Template"> 
    <Setter.Value> 
     <ControlTemplate TargetType="{x:Type TabItem}"> 
      <Grid Height="20" 
         Background="{TemplateBinding Background}" 
         SnapsToDevicePixels="True"> 
       <Grid.ColumnDefinitions> 
       <ColumnDefinition Width="Auto"/> 
       <ColumnDefinition Width="20"/> 
       </Grid.ColumnDefinitions> 
       <ContentPresenter Grid.Column="0" 
           Margin="10,0,10,0" 
           HorizontalAlignment="Center" 
           VerticalAlignment="Center" 
           ContentSource="Header" /> 
       <Button Grid.Column="1" 
         x:Name="CloseButton" 
         Width="15" 
         Height="15" 
         HorizontalAlignment="Center" 
         VerticalAlignment="Center" 
         DockPanel.Dock="Right" 
         AttachedCommand:CommandBehavior.Event="Click" 
         AttachedCommand:CommandBehavior.Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, 
                     Path=DataContext.CloseWorkspaceCommand}"> 
       ... 

以下樣式現在,我想使對TabItem可選的Button可以在DataTemplate

<DataTemplate x:Key="WorkspaceTemplate"> 
    <TabControl x:Name="tabControl" 
       IsSynchronizedWithCurrentItem="true" 
       Style="{StaticResource StudioTabControl}" 
       ItemsSource="{Binding Workspaces}" 
       SelectedIndex="{Binding SelectedIndex, NotifyOnSourceUpdated=True, Mode=TwoWay}"> 
     <TabControl.ItemContainerStyle> 
      <Style TargetType="TabItem" 
        BasedOn="{StaticResource SubStudioTabItem}"> 
       <Setter Property="??Button.Visibility??" Value="{Binding Path=Display, Converter={StaticResource BooleanToVisibiltyConverter}}"/> 
      </Style> 
     </TabControl.ItemContainerStyle> 
    </TabControl> 
</DataTemplate> 
使用的可視性

如何從DataTemplate中設置TabItem上按鈕可見性的狀態?

謝謝你的時間。

回答

1

在這種情況下,我會創造一個附加屬性,如類型的Visibility並會在Style做出TemplateBinding,是這樣的:

<ControlTemplate TargetType="{x:Type TabItem}"> 
... 
    <Button Grid.Column="1" 
       x:Name="CloseButton" 
       Visibility="{TemplateBinding local:MyClass.ButtonVisibility}" 
       ... 
    </Button> 

併爲<ItemContainerStyle>TabItem會寫這個(或其他地方):

<Style TargetType="TabItem" BasedOn="{StaticResource SubStudioTabItem}"> 
    <Setter Property="local:MyClass.ButtonVisibility" Value="{Binding Path=Display, Converter={StaticResource BooleanToVisibiltyConverter}}"/> 
</Style> 

Edit:

我創建了一個實現此方法的項目。在該項目試圖遵循MVVM模式。該項目的結構:

enter image description here

開始按順序在文件夾AttachedProperties有一個附加屬性,它負責Button的外觀。

ButtonVisibility.cs代碼:

using System; 
using System.Windows; 

public class ButtonVisibilityPro : DependencyObject 
{ 
    public static readonly DependencyProperty ButtonVisibilityProperty; 

    public static void SetButtonVisibility(DependencyObject DepObject, Visibility value) 
    { 
     DepObject.SetValue(ButtonVisibilityProperty, value); 
    } 

    public static Visibility GetButtonVisibility(DependencyObject DepObject) 
    { 
     return (Visibility)DepObject.GetValue(ButtonVisibilityProperty); 
    } 

    static ButtonVisibilityPro() 
    { 
     PropertyMetadata MyPropertyMetadata = new PropertyMetadata(Visibility.Collapsed); 

     ButtonVisibilityProperty = DependencyProperty.RegisterAttached("ButtonVisibility", 
                  typeof(Visibility), 
                  typeof(ButtonVisibilityPro), 
                  MyPropertyMetadata); 
    } 
} 

數據模型是ButtonModel,其中所述布爾屬性是ButtonDisplay。該類繼承自ViewModelBase,該類實現INotifyPropertyChanged

ButtonModel.cs

using System; 
using ButtonVisibilityHelp.ViewModels; 

namespace ButtonVisibilityHelp.Models 
{ 
    public class ButtonModel : ViewModelBase 
    { 
     private bool _buttonDisplay = false; 

     public bool ButtonDisplay 
     { 
      get 
      { 
       return _buttonDisplay; 
      } 

      set 
      { 
       _buttonDisplay = value; 
       NotifyPropertyChanged("ButtonDisplay");    
      } 
     } 
    } 
} 

ViewModelBase.cs

using System; 
using System.ComponentModel; 

namespace ButtonVisibilityHelp.ViewModels 
{ 
    public class ViewModelBase : INotifyPropertyChanged 
    { 
     public event PropertyChangedEventHandler PropertyChanged; 

     protected void NotifyPropertyChanged(string propertyName) 
     { 
      if (PropertyChanged != null) 
      { 
       PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
      } 
     } 
    } 
} 

ButtonViewModel.cs

using System; 
using System.Windows.Input; 
using System.Windows; 

using ButtonVisibilityHelp.Models; 
using ButtonVisibilityHelp.Workers; 

namespace ButtonVisibilityHelp.ViewModels 
{ 
    public class ButtonViewModel : ViewModelBase 
    { 
     private ButtonModel _buttonModel; 

     private ICommand _hideButtonCommand = null; 
     private ICommand _showButtonCommand = null; 

     public ButtonModel ButtonModel 
     { 
      get 
      { 
       return _buttonModel; 
      } 

      set 
      { 
       _buttonModel = value; 
       NotifyPropertyChanged("ButtonModel"); 
      } 
     } 

     public ICommand HideButtonCommand 
     { 
      get 
      { 
       if (_hideButtonCommand == null) 
       { 
        _hideButtonCommand = new RelayCommand(param => this.HideButton(), null); 
       } 

       return _hideButtonCommand; 
      } 
     } 

     public ICommand ShowButtonCommand 
     { 
      get 
      { 
       if (_showButtonCommand == null) 
       { 
        _showButtonCommand = new RelayCommand(param => this.ShowButton(), null); 
       } 

       return _showButtonCommand; 
      } 
     } 

     public ButtonViewModel() 
     { 
      ButtonModel = new ButtonModel(); 
     } 

     private void HideButton() 
     {    
      ButtonModel.ButtonDisplay = false; 
     } 

     private void ShowButton() 
     { 
      ButtonModel.ButtonDisplay = true; 
     } 
    } 
} 

RelayCommand.cs

using System; 
using System.Windows.Input; 

namespace ButtonVisibilityHelp.Workers 
{ 
    public class RelayCommand : ICommand 
    { 
     private readonly Action<object> _execute; 
     private readonly Predicate<object> _canExecute; 

     public RelayCommand(Action<object> execute) : this(execute, null) 
     { 
     } 

     public RelayCommand(Action<object> execute, Predicate<object> canExecute) 
     { 
      if (execute == null) 
      { 
       throw new ArgumentNullException("execute"); 
      } 

      _execute = execute; 
      _canExecute = canExecute; 
     } 

     public bool CanExecute(object parameter) 
     { 
      return _canExecute == null ? true : _canExecute(parameter); 
     } 

     public event EventHandler CanExecuteChanged 
     { 
      add 
      { 
       CommandManager.RequerySuggested += value; 
      } 

      remove 
      { 
       CommandManager.RequerySuggested -= value; 
      } 
     } 

     public void Execute(object parameter) 
     { 
      _execute(parameter); 
     } 
    } 
} 

下面是一塊XAML代碼是在TabItem樣式:

<Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type TabItem}"> 
       <Grid Background="{TemplateBinding Background}"> 
        <Grid.ColumnDefinitions> 
         <ColumnDefinition Width="Auto"/> 
         <ColumnDefinition Width="20"/> 
        </Grid.ColumnDefinitions> 

        <Border Grid.Column="0" SnapsToDevicePixels="True" Name="Border" Margin="0,0,2,0" Padding="2" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="0"> 
         <ContentPresenter Name="ContentSite" 
               HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
               Margin="5,5,5,5" 
               VerticalAlignment="Center" 
               RecognizesAccessKey="True" 
               ContentSource="Header" />        
        </Border> 

        <!-- Here TemplateBinding for Visibility --> 
        <Button Name="CloseButton" Style="{StaticResource CloseButton}" 
           Visibility="{TemplateBinding AttachedProperties:ButtonVisibilityPro.ButtonVisibility}" 
           Grid.Column="1" Width="14" Height="14" HorizontalAlignment="Center" /> 
       </Grid> 

       <ControlTemplate.Triggers> 
        <Trigger Property="TabStripPlacement" Value="Bottom"> 
         <Setter TargetName="Border" Property="CornerRadius" Value="0,0,0,0" /> 
        </Trigger>        
       </ControlTemplate.Triggers> 
      </ControlTemplate> 
     </Setter.Value> 
</Setter> 

XAML的MainWindow

<Window x:Class="ButtonVisibilityHelp.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:ViewModels="clr-namespace:ButtonVisibilityHelp.ViewModels" 
    xmlns:AttachedProperties="clr-namespace:ButtonVisibilityHelp.AttachedProperties" 
    WindowStartupLocation="CenterScreen" 
    Title="MainWindow" Height="350" Width="525"> 

    <Window.Resources> 
     <ViewModels:ButtonViewModel x:Key="MyButtonViewModel" /> 
     <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" /> 
    </Window.Resources> 

    <Grid DataContext="{Binding Source={StaticResource MyButtonViewModel}}"> 
     <TabControl> 
      <TabControl.ItemContainerStyle> 
       <Style TargetType="{x:Type TabItem}" BasedOn="{StaticResource {x:Type TabItem}}"> 
        <Setter Property="AttachedProperties:ButtonVisibilityPro.ButtonVisibility" Value="{Binding Path=ButtonModel.ButtonDisplay, Converter={StaticResource BooleanToVisibilityConverter}}" /> 
       </Style> 
      </TabControl.ItemContainerStyle> 

      <TabItem Header="Test1"> 
       <StackPanel> 
        <TextBlock Text="{Binding ButtonModel.ButtonDisplay, StringFormat=ButtonDisplay: {0}, Mode=TwoWay}" HorizontalAlignment="Right" /> 

        <Button Name="ShowInTest1" Command="{Binding ShowButtonCommand}" Width="100" Height="30" Content="Show me" HorizontalAlignment="Right" /> 
        <Button Name="HideInTest1" Command="{Binding HideButtonCommand}" Width="100" Height="30" Content="Hide me" HorizontalAlignment="Right" />     
       </StackPanel> 
      </TabItem> 

      <TabItem Header="Test2"> 
       <StackPanel> 
        <TextBlock Text="{Binding ButtonModel.ButtonDisplay, StringFormat=ButtonDisplay: {0}, Mode=TwoWay}" HorizontalAlignment="Right" /> 

        <Button Name="ShowInTest2" Command="{Binding ShowButtonCommand}" Width="100" Height="30" Content="Show me" HorizontalAlignment="Right" /> 
        <Button Name="HideInTest2" Command="{Binding HideButtonCommand}" Width="100" Height="30" Content="Hide me" HorizontalAlignment="Right" /> 
       </StackPanel> 
      </TabItem> 
     </TabControl> 
    </Grid> 
</Window> 

Output

告訴我:

enter image description here

隱藏我:

enter image description here

完整的代碼示例可在此link

+0

我有困難這個例子。你能讓它更完整嗎? – MoonKnight

+0

@ Killercam:是的,就像時間一樣,我會做的。我很抱歉,那立刻沒有提供完整的代碼。 –

+0

非常感謝您的時間... – MoonKnight

0

設置Tag財產上的TabItem風格象下面這樣:

<TabControl.ItemContainerStyle> 
     <Style TargetType="TabItem" 
       BasedOn="{StaticResource SubStudioTabItem}"> 
      <Setter Property="Tag" Value="{Binding IsVisible, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"/> 
     </Style> 
    </TabControl.ItemContainerStyle> 

然後在ControlTemplate添加DataTrigger設置CloseButton的Visibility根據標記屬性

<ControlTemplate.Triggers> 
    <DataTrigger Binding="{Binding Tag}", Value="false"> 
    <Setter Property="Visibility" TargetName="CloseButton" Value="Collapsed"/> 
    </DataTrigger> 
</ControlTemplate.Triggers> 
+0

但是這不允許我綁定到按鈕的可見性。我需要根據加載的ViewModel更改按鈕的可見性。 – MoonKnight

+0

查看更新的答案..您可以將Tag屬性綁定到VM屬性IsVisible,然後在ControlTemplate觸發器中使用它 – Nitin