2017-10-19 35 views
0

J'ai donc le code xaml suivant dans wpf. Ce qui me donne un DropdownButton se comporter comme je l'attendrais.Comportement ToggleButton avec Popup dans CustomControl

<ToggleButton Content="Test" 
        VerticalAlignment="Center" 
        Focusable="False" 
        IsChecked="{Binding IsOpen, ElementName=Popup, Mode=TwoWay}" 
        Height="25" 
        Width="20" 
        x:Name="btn"> 
     <ToggleButton.Style> 
      <Style TargetType="{x:Type ToggleButton}"> 
       <Style.Triggers> 
        <DataTrigger Binding="{Binding IsOpen, ElementName=Popup}" Value="True"> 
         <Setter Property="IsHitTestVisible" Value="False" /> 
        </DataTrigger> 
       </Style.Triggers> 
      </Style> 
     </ToggleButton.Style> 
    </ToggleButton> 

    <Popup Placement="Bottom" 
      PlacementTarget="{Binding ElementName=btn}" 
      x:Name="Popup" 
      StaysOpen="False"> 
     <TextBlock Background="AliceBlue">Bla</TextBlock> 
    </Popup> 

maintenant que j'utilise cela plusieurs fois je voulais créer un contrôle personnalisé.

Jusqu'à présent, la classe ressemble à ceci:

public class CustomDropdownButton : ToggleButton 
{ 
    public static readonly DependencyProperty DropdownContentProperty = DependencyProperty.Register("DropdownContent", typeof(UIElement), typeof(CustomDropdownButton)); 

    static CustomDropdownButton() 
    { 
     DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomDropdownButton), new FrameworkPropertyMetadata(typeof(CustomDropdownButton))); 
    } 

    public UIElement DropdownContent 
    { 
     get 
     { 
      return (UIElement)GetValue(DropdownContentProperty); 
     } 
     set 
     { 
      SetValue(DropdownContentProperty, value); 
     } 
    } 
} 

et je modifié le style, il ressemble à ceci:

<Style x:Key="ButtonFocusVisual"> 
    <Setter Property="Control.Template"> 
     <Setter.Value> 
      <ControlTemplate> 
       <Rectangle StrokeDashArray="1 2" StrokeThickness="1" 
          Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" 
          SnapsToDevicePixels="true" Margin="2"/> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 
<LinearGradientBrush x:Key="ButtonNormalBackground" EndPoint="0,1" StartPoint="0,0"> 
    <GradientStop Color="#F3F3F3" Offset="0"/> 
    <GradientStop Color="#EBEBEB" Offset="0.5"/> 
    <GradientStop Color="#DDDDDD" Offset="0.5"/> 
    <GradientStop Color="#CDCDCD" Offset="1"/> 
</LinearGradientBrush> 
<SolidColorBrush x:Key="ButtonNormalBorder" Color="#FF707070"/> 

<Style TargetType="{x:Type local:CustomDropdownButton}"> 
    <Setter Property="FocusVisualStyle" Value="{StaticResource ButtonFocusVisual}"/> 
    <Setter Property="Background" Value="{StaticResource ButtonNormalBackground}"/> 
    <Setter Property="BorderBrush" Value="{StaticResource ButtonNormalBorder}"/> 
    <Setter Property="BorderThickness" Value="1"/> 
    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/> 
    <Setter Property="HorizontalContentAlignment" Value="Center"/> 
    <Setter Property="VerticalContentAlignment" Value="Center"/> 
    <Setter Property="Padding" Value="1"/> 
    <Setter Property="ClickMode" Value="Press"/> 
    <Setter Property="Focusable" Value="False"/> 
    <Setter Property="IsChecked" Value="{Binding IsOpen, ElementName=Popup, Mode=TwoWay}"/> 
    <Setter Property="Template"> 
     <Setter.Value> 
      <ControlTemplate TargetType="{x:Type local:CustomDropdownButton}"> 

       <themes:ButtonChrome x:Name="Chrome" 
            BorderBrush="{TemplateBinding BorderBrush}" 
            Background="{TemplateBinding Background}" 
            RenderMouseOver="{TemplateBinding IsMouseOver}" 
            SnapsToDevicePixels="true"> 
        <StackPanel Orientation="Horizontal" 
           IsHitTestVisible="True"> 
         <ContentPresenter Content="{TemplateBinding Content}" 
              HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
              VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
              Margin="5,0,0,0"/> 
         <Path x:Name="ArrowPath" 
           Margin="7,3,3,2" 
           Fill="Gray" 
           Stroke="Gray" 
           StrokeThickness="1" 
           StrokeStartLineCap="Round" 
           StrokeEndLineCap="Round" 
           Stretch="Uniform" 
           VerticalAlignment="Center" 
           HorizontalAlignment="Center" 
           RenderTransformOrigin=".5,.5" 
           Data="M0,0 L2,0 L4,2 L5,3 L6,2 L8,0 L10,0 L8,2 L5,7 L2,2 z"> 
          <Path.RenderTransform> 
           <RotateTransform Angle="-90"/> 
          </Path.RenderTransform> 
         </Path> 

         <Popup Placement="Bottom" 
           x:Name="Popup" 
           StaysOpen="False" 
           Child="{TemplateBinding DropdownContent}"/> 
        </StackPanel> 
       </themes:ButtonChrome> 

       <ControlTemplate.Triggers> 
        <DataTrigger Binding="{Binding IsOpen, ElementName=Popup}" Value="True"> 
         <Setter Property="IsHitTestVisible" Value="False" /> 
        </DataTrigger> 
        <Trigger Property="IsKeyboardFocused" Value="true"> 
         <Setter Property="RenderDefaulted" TargetName="Chrome" Value="true"/> 
        </Trigger> 
        <Trigger Property="IsEnabled" Value="false"> 
         <Setter Property="Foreground" Value="#ADADAD"/> 
        </Trigger> 
        <Trigger Property="IsChecked" Value="False"> 
         <Trigger.EnterActions> 
          <BeginStoryboard> 
           <Storyboard> 
            <DoubleAnimation Storyboard.TargetName="ArrowPath" 
                Storyboard.TargetProperty="RenderTransform.(RotateTransform.Angle)" 
                To="-90" 
                Duration="0:0:0.2"/> 
           </Storyboard> 
          </BeginStoryboard> 
         </Trigger.EnterActions> 
         <Trigger.ExitActions> 
          <BeginStoryboard> 
           <Storyboard> 
            <DoubleAnimation Storyboard.TargetName="ArrowPath" 
                Storyboard.TargetProperty="RenderTransform.(RotateTransform.Angle)" 
                To="0" 
                Duration="0:0:0.2"/> 
           </Storyboard> 
          </BeginStoryboard> 
         </Trigger.ExitActions> 
        </Trigger> 
       </ControlTemplate.Triggers> 
      </ControlTemplate> 
     </Setter.Value> 
    </Setter> 
</Style> 

Le code exemple pour le bouton contextuel fonctionne à merveille. Je pensais obtenir le même effet en utilisant un Setter pour lier la propriété IsOpen du popup à la propriété IsChecked du ToggleButton. Est-ce que je n'ai pas le comportement de déclenchement que je dois ajouter? Je n'arrive pas à comprendre pourquoi il ne s'ouvrira pas.


fixe en supprimant le IsChecked et ClickMode Setter, lié la propriété IsOpen dans le menu contextuel pas TemplateBinding mais avec le RelativeSource suggéré liaison au IsChecked, avec le mode réglé sur TwoWay. StaysOpen et le DataTrigger ont été conservés.

Popup toujours fermé en raison d'une marge que j'ai définie pour les ListViewItems dans le ListView. Définissez un remplissage (toujours cliquable) ou une marge (ne rien toucher) pour le détenteur du contenu. Pour moi, c'était une case à cocher dans le ListView.

Répondre

1

Bind la propriété IsOpen du Popup dans le modèle à la propriété IsChecked du contrôle:

<Popup Placement="Bottom" 
     x:Name="Popup" 
     StaysOpen="False" 
     IsOpen="{Binding Path=IsChecked, RelativeSource={RelativeSource AncestorType=local:CustomDropdownButton}, Mode=TwoWay}" 
     Child="{TemplateBinding DropdownContent}"/> 

Cela ne fonctionnera pas:

<Setter Property="IsChecked" Value="{Binding IsOpen, ElementName=Popup, Mode=TwoWay}"/> 
+0

... et si StaysOpen est faux, configurer un déclencheur pour désactiver le ToggleButton alors que 'Popup.IsOpen' est vrai. Sinon, lorsque l'utilisateur clique sur ToggleButton alors que la fenêtre contextuelle est ouverte, le flou de focus fermera le popup (OK jusqu'ici), suivi par le ToggleButton maintenant décoché qui reçoit un clic et rouvre le popup (frustrant). –

+0

Je l'ai déjà essayé, le problème est que le popup ne se ferme pas quand je clique dessus, il ne réagit pas quand je clique sur le bouton, ce qui est expliqué dans le commentaire. Je ne veux pas vraiment désactiver le bouton quand la popup est ouverte cependant. La popup ne se ferme que lorsque je clique entre les entrées ListView il est rempli – SireChicken

+0

Mise à jour: ayant comme ça me permet de fermer la fenêtre en cliquant sur le bouton, pas de problème là-bas. Mais il ne se ferme pas lorsque je clique à l'extérieur de celui-ci et il se ferme quand on clique entre les éléments. J'ai retiré le Datatrigger pour qu'il fonctionne – SireChicken