2013-10-11 4 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}"> 
       ... 

Теперь я хочу, чтобы сделать видимость Button на TabItem факультативный, который может быть использован в 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> 

Как установить состояние видимости кнопки на TabItem с DataTemplate?

Спасибо за ваше время.

ответ

1

В этом случае, я бы создал прикрепленную собственности, такие как тип Visibility и сделает TemplateBinding в Style, что-то вроде этого:

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

И для TabItem в <ItemContainerStyle> бы написать это (или где-то еще):

<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

Start в порядке, в папке 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

@ Киллеркам: Да, как и время, я сделаю. Извините, что сразу не предоставил полный код. –

+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 установить Visibility из CloseButton в зависимости от категории имущества

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

Но это не позволяет мне привязываться к видимости кнопки. Мне нужно изменить видимость кнопки в зависимости от загруженного ViewModel. – MoonKnight

+0

см. Обновленный ответ .. вы можете привязать свойство тега к свойству VM IsVisible, а затем использовать его в триггере ControlTemplate – Nitin

Смежные вопросы