2016-06-27 9 views
0

Ich benutze MahApps und MVVM Light. Und ich möchte DropDownButton öffnet bei Mauseingabe. Und verstecken Sie es, wenn der Mauszeiger die Taste und das geöffnete Menü verlässt. Zur Code-Vereinfachung schreibe ich keinen Code mit EventToCommand. Ich schreibe gerade Code hinterUnd wieder. Lassen Sie DropDownButton auf Maus öffnen und ausblenden, wenn Maus verlässt

XAML

   <controls:DropDownButton x:Name="ddbVolume" Width="{Binding Path=ActualHeight, RelativeSource={RelativeSource Self}}" 
            ItemsSource="{Binding AudioControls}" 
            Icon="{DynamicResource appbar_settings}" BorderThickness="0" 
            ArrowVisibility="Collapsed" 
            Loaded="OnDropDownButtonLoaded" MouseEnter="OnDropDownButtonMouseEnter"> 

      </controls:DropDownButton> 

und CS-

private void OnDropDownButtonMouseEnter(object sender, MouseEventArgs e) 
    { 
     var dropDownButton = sender as DropDownButton; 
     if (dropDownButton != null && !dropDownButton.IsExpanded) 
     { 
      dropDownButton.IsExpanded = true; 
     } 
    } 

    private void OnDropDownButtonLoaded(object sender, RoutedEventArgs e) 
    { 
     var dropDownButton = sender as DropDownButton; 
     if (dropDownButton != null) 
     { 
      var template = dropDownButton.Template; 
      var menu = (ContextMenu)template.FindName("PART_Menu", dropDownButton); 
      menu.MouseLeave += (o, args) => 
      { 
       if (dropDownButton.IsExpanded && !dropDownButton.IsMouseOver && !menu.IsMouseOver) 
       { 
        dropDownButton.IsExpanded = false; 
       } 
      }; 
      menu.PreviewMouseMove += (o, args) => 
      { 
       if (!dropDownButton.IsExpanded) 
       { 
        return; 
       } 

       var x = args.GetPosition(menu).X; 
       var y = args.GetPosition(menu).Y; 
       if (x < 0 | y < 0 | x > menu.ActualWidth | y > menu.ActualHeight) 
       { 
        menu.ReleaseMouseCapture(); 
       } 
      }; 
     } 
     else 
     { 
      this._logger.Debug($"Error loading DropDownButton"); 
     } 

Aber es funktioniert nicht. Der DropDownButton flimmert nur bei Mausüberlauf. Bitte geben Sie mir eine geeignete Lösung oder einen nützlichen Rat zur Lösung dieses Problems.

Antwort

0

Wenn das Menü überhaupt erscheint, dann ist Ihre Eröffnungslogik gut, aber dann verschwindet es, was bedeutet, dass Ihr eigener Code es irgendwie schließt.

Halte einen Haltepunkt in der Zeile, wo du dropDownButton.IsExpanded = false gesetzt hast, und du wirst sehen, dass es heißt, ich bin mir sicher. Sie können dann den Debugger verwenden, um zu sehen, warum er aufgerufen wurde, und das Problem in Ihrem XAML beheben, das dazu führt, dass das System denkt, dass Ihre Maus das Menü verlassen hat.

+0

das Problem war, dass dropDownButton.IsMouseOver ist immer falsch – Anton

0

Vielleicht sollten Sie das MouseLeave Event abonnieren. Und du könntest deine Aktionen reparieren.

+0

ich abonniert, aber nicht für die Hauptsteuerung, noch für seine logische Kind Kontrolle – Anton

0

Ich habe eine Lösung gemacht. Und es funktioniert wie ich es erwarte. Der Grund des Problems war, dass DropDownButton ContextMenu zum Anzeigen von Listenelementen verwendet. Und dieses Steuerelement basiert auf Popup, das sein eigenes Fenster verwendet. Und MouseLeave feuerte nicht zur Zeit, wenn der Mauszeiger nicht darüber war, sondern wenn der Fokus verloren war.

XAML

   <controls:DropDownButton x:Name="ddbVolume" Width="{Binding Path=ActualHeight, RelativeSource={RelativeSource Self}}" 
            ItemsSource="{Binding AudioControls}" 
            Icon="{DynamicResource appbar_settings}" BorderThickness="0" 
            ArrowVisibility="Collapsed"> 
       <i:Interaction.Triggers> 
        <i:EventTrigger EventName="Loaded"> 
         <command:EventToCommand Command="{Binding Source={x:Static commands:CommonCommands.DropDownButtonLoadedCommand}}" PassEventArgsToCommand="True"/> 
        </i:EventTrigger> 
        <i:EventTrigger EventName="MouseEnter"> 
         <command:EventToCommand Command="{Binding Source={x:Static commands:CommonCommands.DropDownButtonMouseEnterCommand}}" PassEventArgsToCommand="True"/> 
        </i:EventTrigger> 
       </i:Interaction.Triggers> 

      </controls:DropDownButton> 

Und ein Ansichtsmodell Code (Ich weiß, es ist kein VM, aber es funktioniert auf die gleiche Art und Weise) In statischen Klasse-I-Befehle definieren, die in meiner Anwendung überall dort eingesetzt werden können.

public static class CommonCommands 
{ 
    private static ICommand dropDownButtonLoadedCommand; 
    private static ICommand dropDownButtonMouseEnterCommand; 

    public static ICommand DropDownButtonLoadedCommand => dropDownButtonLoadedCommand; 
    public static ICommand DropDownButtonMouseEnterCommand => dropDownButtonMouseEnterCommand; 

    static CommonCommands() 
    { 
     dropDownButtonLoadedCommand = new RelayCommand<RoutedEventArgs>(DropDownButtonLoaded, x => true); 
     dropDownButtonMouseEnterCommand = new RelayCommand<MouseEventArgs>(DropDownButtonMouseEnter, x => true); 
    } 

    private static void DropDownButtonLoaded(RoutedEventArgs args) 
    { 
     var dropDownButton = args.Source as DropDownButton; 
     if (dropDownButton != null) 
     { 
      var template = dropDownButton.Template; 
      var menu = (ContextMenu)template.FindName("PART_Menu", dropDownButton); 
      var button = (Button)template.FindName("PART_Button", dropDownButton); 
      menu.MouseLeave += (o, e) => 
      { 
       if (dropDownButton.IsExpanded && !dropDownButton.IsMouseOver && !menu.IsMouseOver) 
       { 
        dropDownButton.IsExpanded = false; 
       } 
      }; 
      menu.PreviewMouseMove += (o, e) => 
      { 
       if (!dropDownButton.IsExpanded || !menu.IsOpen) 
       { 
        return; 
       } 

       var x = e.GetPosition(menu).X; 
       var y = e.GetPosition(menu).Y; 
       if (x < 0 | y < -button.ActualHeight | x > menu.ActualWidth | y > menu.ActualHeight) 
       { 
        menu.ReleaseMouseCapture(); 
       } 
      }; 
     } 
    } 

    private static void DropDownButtonMouseEnter(MouseEventArgs args) 
    { 
     var dropDownButton = args.Source as DropDownButton; 
     if (dropDownButton != null && !dropDownButton.IsExpanded) 
     { 
      dropDownButton.IsExpanded = true; 
     } 
    } 
} 

Ich weiß, dass es ein paar kleine Mängel gibt. Zum Beispiel ist "Ausdruck y < -button.ActualHeight" überhaupt nicht gut. Die richtige Methode ist die Verwendung von button.IsMouseOver im MouseLeave-Ereignis.

Verwandte Themen