是否可以在WPF / Touch应用程序中使用弹出窗口忽略MenuDropAlignment?

时间:2011-02-17 09:39:08

标签: wpf xaml touch multi-touch multidatatrigger

作为一个背景--Windows有一个Touch / TabletPCs设施,它根据你的“用手”改变弹出菜单/菜单的位置(以防止菜单出现在你的手下)。

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

平板电脑设置设为左手 - 无法从Windows进行人工修正 Tablet PC Settings set to Left handed - no artificial correction from Windows

平板电脑设置设置为右手 - Windows人工调整我们的定位 Tablet PC Settings set to Right handed - Windows artificially adjusts our positioning

我们可以使用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}

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

5 个答案:

答案 0 :(得分: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

答案 1 :(得分:3)

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

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

fi.SetValue(null, false);

答案 2 :(得分: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中,它仅在PlacementModeRelativeAbsolutePointRelativePoint或{{1}时检查MousePoint }。如果您可以使用其中一个PlacementModes,则不会受到MenuDropAlignment检查。

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

来源:反射器

答案 3 :(得分:0)

这已经很老了,但是如果您至少拥有.net 4.5,我发现了另一种方法。

通过覆盖菜单项/弹出模板,您可以使用以下触发器:

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

当然,请设置以下内容:

  • 对您的数据触发值是对还是错,
  • 向左或向右作为您的设置器值。

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

答案 4 :(得分:-1)

看起来这是不可能的,所以我们在问题中使用MultiDataTrigger进行补偿。