2016-06-27 39 views
0

我正在使用MahApps和MVVM Light。我想讓DropDownButton在鼠標輸入時打開。當鼠標光標離開按鈕並打開菜單時隱藏它。爲了簡化代碼,我不使用EventToCommand編寫代碼。我只寫代碼背後再次。使DropDownButton在mouseEnter上打開並在鼠標離開時隱藏

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> 

和的.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"); 
     } 

但它不工作。 DropDownButton只在鼠標懸停時閃爍。請給我一個適當的解決方案,或任何有用的建議來解決這個問題。

回答

0

如果菜單完全出現,那麼你的開放邏輯是好的,但它會消失,這意味着你自己的代碼以某種方式關閉它。

在你設置dropDownButton.IsExpanded = false的行上貼一個斷點,你會看到這就是我正在調用的。然後,您可以使用調試器來查看調用的原因並解決xaml中導致系統認爲鼠標已經離開菜單的問題。

+0

問題是,dropDownButton.IsMouseOver總是假的 – Anton

0

也許,你應該訂閱MouseLeave事件。你可以修復你的行爲。

+0

我訂閱了它,但不是主要控制,但它的邏輯子控件 – Anton

0

我已經提出了一個解決方案。它和我預期的一樣。問題的根源在於,DropDownButton使用ContextMenu來顯示列表項。而這個控件基於Popup,它使用了自己的窗口。當鼠標沒有超過它時,MouseLeave沒有發射,但是當它失去焦點時。

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> 

而且一個視圖模型代碼(我知道這不是一個虛擬機,但它的工作方式相同) 在靜態類我定義了可以在任何地方在我的應用程序中使用的命令。

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; 
     } 
    } 
} 

我知道有一些小缺陷。例如,「表達y < -button.ActualHeight」根本不好。正確的方法是在MouseLeave事件中使用button.IsMouseOver。

相關問題