是否可以在 WPF / Touch 应用程序中弹出一个忽略 MenuDropAlignment 的窗口?
作为一点背景知识 - Windows 有一个针对触摸/平板电脑的功能,它可以根据您的“用手习惯”来移动弹出窗口/菜单的位置(以防止菜单出现在您的手下)。
从本质上讲,如果您设置为“右手”(连接触摸设备后似乎默认为右手),您打开的每个弹出窗口都会被人为地踢到左侧 - 这会导致我们尝试的大量布局问题并将弹出窗口与其“从中弹出”的项目对齐:
平板电脑设置设置为左手 - Windows 无需人工修正
平板电脑设置设置为右手 - Windows 人为修正调整我们的定位
我们可以使用 SystemParameters.MenuDropAlignment,对于简单的弹出窗口,我们可以调整它使用弹出窗口的实际宽度 - 但对于动态弹出窗口,当我们将从右到左的支持添加到混合中时,这不起作用。
目前看来,我们更有可能必须检查每个弹出窗口,手动计算出一个值来调整踢,然后为每个弹出窗口添加类似的内容:
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Source={x:Static SystemParameters.MenuDropAlignment}}" Value="True"/>
<Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=FlowDirection}" Value="RightToLeft"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="HorizontalOffset" Value="-50"/> <!-- Set to arbitrary value to test -->
</MultiDataTrigger.Setters>
</MultiDataTrigger>
所以..回到问题:-) 有谁知道有办法阻止 WPF 弹出窗口查看此设置吗?
对于没有触摸设备的用户,您可以通过运行以下命令来访问 Tablet PC 设置:
C:\Windows\explorer.exe shell:::{80F3F1D5-FECA-45F3-BC32-752C152E456E}
并查看它造成的混乱你自己 :-)
As a bit of background - Windows has a facility for Touch/TabletPCs whereby it shifts the position of popups/menus depending on your "handedness" (to prevent the menu appearing under your hand).
Essentially what this does is if you are set to "right handed" (which it seems to default to once you've connected a touch device), every popup you open is artificially kicked to the left - this causes massive layout issues where we try and line up a popup with the item it "popped up from" :
Tablet PC Settings set to Left handed - no artificial correction from Windows
Tablet PC Settings set to Right handed - Windows artificially adjusts our positioning
We can detect what this setting is set to with SystemParameters.MenuDropAlignment, and for trivial popups we can adjust this using the actual width of the popup - but for dynamic popups and when we throw right to left support into the mix, this just doesn't work.
Currently it's looking more likely that we are going to have to go through every popup, manually work out a value to adjust the kick, and add something like this to every one:
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Source={x:Static SystemParameters.MenuDropAlignment}}" Value="True"/>
<Condition Binding="{Binding RelativeSource={RelativeSource Mode=Self}, Path=FlowDirection}" Value="RightToLeft"/>
</MultiDataTrigger.Conditions>
<MultiDataTrigger.Setters>
<Setter Property="HorizontalOffset" Value="-50"/> <!-- Set to arbitrary value to test -->
</MultiDataTrigger.Setters>
</MultiDataTrigger>
So.. back to the question :-) Does anyone know of a way to stop a WPF popup looking at this setting at all?
For those that don't have a touch device you can access the Tablet PC settings by running:
C:\Windows\explorer.exe shell:::{80F3F1D5-FECA-45F3-BC32-752C152E456E}
And see the mess it makes for yourself :-)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
我编写了一个自定义弹出窗口来解决这个问题:您可以设置 ForceAlignment 依赖属性并使用“Open”方法将其打开,也可以直接调用“OpenLeft”和“OpenRight”方法。
I wrote a custom popup that solve this problem: you can set the ForceAlignment dependency property and open it with the "Open" method, or you can directly call "OpenLeft" and "OpenRight" methods.
将其设置为整个应用程序的常规模式:
Set it to regular mode for your whole application:
这已经很老了,但如果你至少有 .net 4.5,我找到了另一种方法。
通过覆盖您的菜单项/弹出窗口模板,您可以使用以下触发器:
当然,设置以下内容:
绑定使用 Binding Path=() 语法而不是 Binding={x:static ...} 非常重要,这样您就可以使用静态类中的 StaticPropertyChanged 事件。
This is pretty old but I found another way if you have .net 4.5 at least.
By overriding your menuitem/popup templates, you can use the following trigger:
Off course, set the following :
It's important that the binding use Binding Path=() syntax and not Binding={x:static ...} so that you can use the StaticPropertyChanged event from your static class.
看来这是不可能的,因此我们求助于问题中的 MultiDataTrigger 来进行补偿。
It would appear this just isn't possible, so we are resorting to the MultiDataTrigger in the question to compensate.
SystemParameters.MenuDropAlignment
用于单个方法:System.Windows.Controls.Primitives.Popup.GetPointCombination()
此私有方法的逻辑取决于
的值>Popup.Placement
,其类型为PlacementMode
:在
GetPointCombination()
中,它仅在MenuDropAlignment
时检查MenuDropAlignment
>PlacementMode 为Relative
、AbsolutePoint
、RelativePoint
或MousePoint
。如果您可以使用其他PlacementModes
之一,那么您将不会受到MenuDropAlignment
检查。如果您使用
PlacementMode.Custom
,那么您还需要将Popup.CustomPopupPlacementCallback
设置为有效方法,以便提供弹出窗口的CustomPopupPlacement[]< /代码> 坐标。
来源:反射器
SystemParameters.MenuDropAlignment
is used in a single method:System.Windows.Controls.Primitives.Popup.GetPointCombination()
This private method has logic that depends upon the value of
Popup.Placement
, which is of typePlacementMode
:In
GetPointCombination()
, it only checks theMenuDropAlignment
when thePlacementMode
isRelative
,AbsolutePoint
,RelativePoint
, orMousePoint
. If you can use one of the otherPlacementModes
then you won't be subject to theMenuDropAlignment
check.If you use
PlacementMode.Custom
, then you'll also want to set thePopup.CustomPopupPlacementCallback
to a valid method in order to provide your popup'sCustomPopupPlacement[]
coordinates.Source: Reflector
除了 Julican 的 答案 之外,如果您不使用 StaticPropertyChanged 事件,
上面的代码中的值可能会有所不同,具体取决于您想要的内容...
另外,请确保您没有将 Placement 属性放置在弹出窗口上:
In addition to Julican's answer if you don't use the StaticPropertyChanged event
In the code above values might differ depending on what you want...
Also, make sure that you didn't place the Placement property on the popup: