我正在使用MahApps和MVVM Light。我想在鼠标输入时打开DropDownButton。当鼠标光标离开按钮并打开菜单时隐藏它。为了简化代码,我不用EventToCommand编写代码。我只是写代码
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 :(得分:0)
如果菜单完全出现,那么你的开放逻辑是好的,但它会消失,这意味着你自己的代码以某种方式关闭它。
在你设置dropDownButton.IsExpanded = false的行上贴一个断点,你会看到它被调用我确定。然后,您可以使用调试器来查看为什么调用它并修复xaml中导致系统认为您的鼠标已离开菜单的问题。
答案 1 :(得分:0)
也许,你应该订阅MouseLeave事件。你可以修复你的行动。
答案 2 :(得分: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>
ViewModel代码(我知道它不是VM,但它的工作方式相同) 在静态类中,我定义了可以在我的应用程序的任何地方使用的命令。
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&lt; -button.ActualHeight”并不是很好。正确的方法是在MouseLeave事件中使用button.IsMouseOver。