我正在尝试从Popup
内的控件执行拖放操作。被拖动的内容将被放置在拖放的位置,因此当拖动开始时,我想让Popup
半透明以允许放置在它下面。但到目前为止,我没有让鼠标事件通过我的半透明Popup
。
以下xaml工作正常,当使用鼠标悬停Button
时,Rectangle
仍可点击
<Grid>
<Rectangle Panel.ZIndex="2"
Width="200"
Height="200"
Fill="Green"
IsHitTestVisible="False"
Opacity="0.5"/>
<Button Content="Click Me"
FontSize="22"
FontWeight="Bold"/>
</Grid>
但是当鼠标悬停在Rectangle
内的Popup
时,以下xaml无法允许鼠标事件通过。
<Grid>
<Popup Placement="Center"
AllowsTransparency="True"
IsHitTestVisible="False"
IsOpen="True">
<Rectangle Width="100"
Height="50"
Fill="Green"
IsHitTestVisible="False"
Opacity="0.5"/>
</Popup>
<Button Content="Click Me"
FontSize="22"
FontWeight="Bold"/>
</Grid>
我已尝试获取PopupRoot
的{{1}}顶级父级,并为视觉树中的每个元素明确设置Rectangle
和IsHitTestVisible
,但它仍然没有不行。我可以通过将Opacity
/ Background
设置为Fill
的唯一方法是将Transparent
/ Transparent
设置为Window
,但它看起来很奇怪并且将非Popup
的部分悬停仍然失败
我已阅读以下链接,但据我所知,这只适用于{{1}}而非{{1}}。 How to create a semi transparent window in WPF that allows mouse events to pass through
有没有人有任何解决方案或建议? : - )
答案 0 :(得分:4)
感谢@NETscape发表的评论,我试图抓住Window
的实际Popup
。它适用于以下代码(最初显示Popup
之后我可能会添加..)
// FromVisual can take any Visual inside the Popup..
HwndSource popupHwndSource = HwndSource.FromVisual(rectangle) as HwndSource;
将此与this question的答案相结合我创建了一个附加行为,该行为添加了可以在IsPopupEventTransparent
中的任何子项上设置的属性Popup
。起初,此解决方案导致了一个错误,该错误迫使用户在Window
失去事件透明度后点击两次以重新激活Popup
。我用&#34; Mouse.Capture
- 解决方法&#34;。
elementInPopup.Dispatcher.BeginInvoke(new Action(() =>
{
Keyboard.Focus(elementInPopup);
Mouse.Capture(elementInPopup);
elementInPopup.ReleaseMouseCapture();
}));
可以这样使用
<Popup AllowsTransparency="True"
...>
<Border inf:PopupBehavior.IsPopupEventTransparent="{Binding SomeProperty}"
BorderThickness="1"
BorderBrush="Black"
Background="White"
Margin="0 0 8 8">
<Border.Effect>
<DropShadowEffect ShadowDepth="2.25"
Color="Black"
Opacity="0.4"
Direction="315"
BlurRadius="4"/>
</Border.Effect>
<!--...-->
</Border>
</Popup>
<强> PopupBehavior 强>
public class PopupBehavior
{
public static readonly DependencyProperty IsPopupEventTransparentProperty =
DependencyProperty.RegisterAttached("IsPopupEventTransparent",
typeof(bool),
typeof(PopupBehavior),
new UIPropertyMetadata(false, OnIsPopupEventTransparentPropertyChanged));
public static bool GetIsPopupEventTransparent(DependencyObject obj)
{
return (bool)obj.GetValue(IsPopupEventTransparentProperty);
}
public static void SetIsPopupEventTransparent(DependencyObject obj, bool value)
{
obj.SetValue(IsPopupEventTransparentProperty, value);
}
private static void OnIsPopupEventTransparentPropertyChanged(DependencyObject target, DependencyPropertyChangedEventArgs e)
{
FrameworkElement element = target as FrameworkElement;
if ((bool)e.NewValue == true)
{
FrameworkElement topParent = VisualTreeHelpers.GetTopParent(element) as FrameworkElement;
topParent.Opacity = 0.4;
HwndSource popupHwndSource = HwndSource.FromVisual(element) as HwndSource;
WindowHelper.SetWindowExTransparent(popupHwndSource.Handle);
}
else
{
FrameworkElement topParent = VisualTreeHelpers.GetTopParent(element) as FrameworkElement;
topParent.Opacity = 1.0;
HwndSource popupHwndSource = HwndSource.FromVisual(element) as HwndSource;
WindowHelper.UndoWindowExTransparent(popupHwndSource.Handle, element);
}
}
}
WindowHelper 根据此this question的回答
public static class WindowHelper
{
private static Dictionary<IntPtr, int> _extendedStyleHwndDictionary = new Dictionary<IntPtr, int>();
const int WS_EX_TRANSPARENT = 0x00000020;
const int GWL_EXSTYLE = (-20);
[DllImport("user32.dll")]
static extern int GetWindowLong(IntPtr hwnd, int index);
[DllImport("user32.dll")]
static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle);
public static void SetWindowExTransparent(IntPtr hwnd)
{
int extendedStyle = GetWindowLong(hwnd, GWL_EXSTYLE);
SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle | WS_EX_TRANSPARENT);
if (_extendedStyleHwndDictionary.Keys.Contains(hwnd) == false)
{
_extendedStyleHwndDictionary.Add(hwnd, extendedStyle);
}
}
public static void UndoWindowExTransparent(IntPtr hwnd, FrameworkElement elementInPopup)
{
if (_extendedStyleHwndDictionary.Keys.Contains(hwnd) == true)
{
int extendedStyle = _extendedStyleHwndDictionary[hwnd];
SetWindowLong(hwnd, GWL_EXSTYLE, extendedStyle);
// Fix Focus problems that forces the users to click twice to
// re-activate the window after the Popup loses event transparency
elementInPopup.Dispatcher.BeginInvoke(new Action(() =>
{
Keyboard.Focus(elementInPopup);
Mouse.Capture(elementInPopup);
elementInPopup.ReleaseMouseCapture();
}));
}
}
}
答案 1 :(得分:0)
问题不在于弹出窗口,但在应用于矩形时问题是颜色为Green
,这会有效阻止鼠标事件通过
尝试使用透明背景的下面的示例,我放置了一个边框来显示存在
<Grid>
<Popup Placement="Center"
AllowsTransparency="True"
IsHitTestVisible="False"
IsOpen="True">
<Border Width="100"
Height="50"
Background="Transparent"
BorderBrush="Black"
BorderThickness="4"
IsHitTestVisible="False"
Opacity="0.5" />
</Popup>
<Button Content="Click Me"
FontSize="22"
FontWeight="Bold" />
</Grid>
因此任何具有non zero alpha
组件的颜色都会阻止鼠标事件
请参阅下面的alpha示例
Fail
Fail
Fail
Pass
因此您需要具有透明色才能通过
传递鼠标事件由于弹出窗口是在应用程序窗口顶部生成的分层窗口,因此如果您需要背景,则可能需要实现如何创建半透明窗口解决方案。在wpf中似乎没有构建解决方案