16

作为背景知识 - Windows 有一个适用于触控/平板电脑的功能,它可以根据您的“惯用手”改变弹出窗口/菜单的位置(以防止菜单出现在您的手下)。

本质上,如果您设置为“右手”(一旦您连接了触摸设备,它似乎默认为),您打开的每个弹出窗口都会被人为地踢到左侧 - 这会导致我们尝试的大量布局问题并将弹出窗口与它“弹出”的项目对齐:

平板电脑设置设置为左手 - 没有来自 Windows 的人为校正 平板电脑设置设置为左手 - 没有来自 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 外壳:::{80F3F1D5-FECA-45F3-BC32-752C152E456E}

看看它给自己造成的混乱:-)

4

5 回答 5

3

我写了一个自定义弹窗来解决这个问题:你可以设置 ForceAlignment 依赖属性并用“Open”方法打开它,也可以直接调用“OpenLeft”和“OpenRight”方法。

Public Class CustomPopup

Inherits Primitives.Popup
Private Shared moFI As Reflection.FieldInfo = GetType(SystemParameters).GetField("_menuDropAlignment", Reflection.BindingFlags.NonPublic + Reflection.BindingFlags.Static)

Public Enum enuForceAlignment
    None = 0
    Left
    Right
End Enum

Public Property ForceAlignment As enuForceAlignment
    Get
        Return GetValue(ForceAlignmentProperty)
    End Get

    Set(ByVal value As enuForceAlignment)
        SetValue(ForceAlignmentProperty, value)
    End Set
End Property
Public Shared ReadOnly ForceAlignmentProperty As DependencyProperty = _
                       DependencyProperty.Register("ForceAlignment", _
                       GetType(enuForceAlignment), GetType(CustomPopup), _
                       New FrameworkPropertyMetadata(enuForceAlignment.None))

Public Sub Open()
    Select Case ForceAlignment
        Case enuForceAlignment.Left
            OpenLeft()
        Case enuForceAlignment.Right
            OpenRight()
        Case Else
            IsOpen = True
    End Select
End Sub
Public Sub OpenRight()
    _Open(False)
End Sub
Public Sub OpenLeft()
    _Open(True)
End Sub
Private Sub _Open(paMenuDropAlignment As Boolean)
    If SystemParameters.MenuDropAlignment <> paMenuDropAlignment Then
        moFI.SetValue(Nothing, paMenuDropAlignment)
        IsOpen = True
        moFI.SetValue(Nothing, Not paMenuDropAlignment)
    Else
        IsOpen = True
    End If
End Sub
End Class
于 2013-01-14T17:50:36.710 回答
2

将其设置为整个应用程序的常规模式:

FieldInfo fi = typeof(SystemParameters).GetField("_menuDropAlignment",
   BindingFlags.NonPublic | BindingFlags.Static);

fi.SetValue(null, false);
于 2013-03-27T22:30:53.753 回答
0

SystemParameters.MenuDropAlignment在单个方法中使用:

System.Windows.Controls.Primitives.Popup.GetPointCombination()

这个私有方法的逻辑取决于 的值Popup.Placement,它的类型是PlacementMode

public enum PlacementMode
{
    Absolute,
    Relative,
    Bottom,
    Center,
    Right,
    AbsolutePoint,
    RelativePoint,
    Mouse,
    MousePoint,
    Left,
    Top,
    Custom
}

GetPointCombination()中,它只检查MenuDropAlignment何时PlacementModeRelativeAbsolutePointRelativePointMousePoint。如果您可以使用其中之一,PlacementModes那么您将不会受到MenuDropAlignment检查。

如果您使用PlacementMode.Custom,那么您还需要将 设置Popup.CustomPopupPlacementCallback为有效方法以提供弹出窗口的CustomPopupPlacement[]坐标。

来源:反射器

于 2011-02-17T17:38:47.043 回答
0

这已经很老了,但如果你至少有 .net 4.5,我找到了另一种方法。

通过覆盖您的 menuitem/popup 模板,您可以使用以下触发器:

<DataTrigger Binding="{Binding Path=(SystemParameters.MenuDropAlignment)}" Value="[True/False]">
    <Setter TargetName="Popup" Property="Placement" Value="[Left/Right]"/>
</DataTrigger>

当然,设置以下内容:

  • 对您的数据触发器值的真或假,
  • 左或右作为您的设置器值。

绑定使用 Binding Path=() 语法而不是 Binding={x:static ...} 很重要,这样您就可以使用静态类中的 StaticPropertyChanged 事件。

于 2018-12-28T15:42:01.213 回答
-1

看起来这是不可能的,所以我们在问题中求助于 MultiDataTrigger 来弥补。

于 2011-07-28T10:37:27.620 回答