trigger style wpf xaml touch multi-touch multidatatrigger

wpf - style datatrigger



¿Es posible hacer que una ventana emergente ignore MenuDropAlignment en una aplicación WPF/Touch? (4)

Como un poco de fondo: Windows tiene una función para Touch / TabletPCs por el cual cambia la posición de las ventanas emergentes / menús en función de su "lateralidad" (para evitar que el menú aparezca bajo su mano).

Esencialmente, lo que hace es que si está configurado como "diestro" (que parece ser el predeterminado una vez que haya conectado un dispositivo táctil), cada ventana emergente que abra se golpea artificialmente hacia la izquierda; esto provoca problemas de diseño masivo donde intentamos y alinee una ventana emergente con el elemento desde el que "apareció".

Configuración de Tablet PC configurada como zurdo: sin corrección artificial desde Windows

Configuraciones de Tablet PC configuradas para diestros: Windows ajusta artificialmente nuestro posicionamiento

Podemos detectar el ajuste de esta configuración con SystemParameters.MenuDropAlignment , y para ventanas emergentes triviales podemos ajustar esto usando el ancho real de la ventana emergente, pero para ventanas emergentes dinámicas y cuando lanzamos soporte de derecha a izquierda en la mezcla, esto simplemente no funciona. t trabajo.

Actualmente, parece más probable que tengamos que pasar por cada ventana emergente, calcular manualmente un valor para ajustar la patada y agregar algo como esto a cada uno:

<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>

Entonces ... de vuelta a la pregunta :-) ¿Alguien sabe de una forma de detener una ventana emergente de WPF mirando esta configuración?

Para aquellos que no tienen un dispositivo táctil, puede acceder a la configuración de Tablet PC ejecutando:

C: / Windows / explorer.exe shell ::: {80F3F1D5-FECA-45F3-BC32-752C152E456E}

Y mira el lío que te hace a ti mismo :-)


Parece que esto simplemente no es posible, por lo que estamos recurriendo a MultiDataTrigger en la pregunta para compensar.


Escribí una ventana emergente personalizada que resuelve este problema: puede establecer la propiedad de dependencia ForceAlignment y abrirla con el método "Abrir", o puede llamar directamente a los métodos "OpenLeft" y "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


Configúrelo en modo regular para toda su aplicación:

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


SystemParameters.MenuDropAlignment se usa en un único método:

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

Este método privado tiene una lógica que depende del valor de Popup.Placement , que es del tipo PlacementMode :

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

En GetPointCombination() , solo comprueba MenuDropAlignment cuando PlacementMode es Relative , AbsolutePoint , RelativePoint o MousePoint . Si puede usar uno de los otros PlacementModes entonces no estará sujeto a la verificación MenuDropAlignment .

Si usa PlacementMode.Custom , también querrá configurar Popup.CustomPopupPlacementCallback en un método válido para proporcionar las CustomPopupPlacement[] de su CustomPopupPlacement[] .

Fuente: Reflector