Ответ 1
Казалось бы, это просто невозможно, поэтому мы прибегаем к MultiDataTrigger в вопросе о компенсации.
В некотором роде - у Windows есть возможность для Touch/TabletPCs, благодаря чему она сдвигает положение всплывающих окон/меню в зависимости от вашей "ручности" (чтобы предотвратить появление меню под рукой).
По сути, это означает, что если вы настроены на "правую руку" (по умолчанию это означает, что когда вы подключили сенсорное устройство), каждое всплывающее окно, которое вы открываете, искусственно ударяется влево - это вызывает массовые проблемы с макетом где мы пытаемся выстроить всплывающее окно с элементом, который он "выскочил":
Настройки планшетного ПК установлены на левую сторону - нет искусственной коррекции из Windows
Настройки планшетного ПК установлены вправо - Windows искусственно настраивает наше позиционирование
Мы можем определить, для чего этот параметр установлен с помощью SystemParameters.MenuDropAlignment, а для тривиальных всплывающих окон мы можем настроить это, используя фактическую ширину popup - но для динамических всплывающих окон и когда мы добавляем поддержку справа налево в микс, это просто не работает.
В настоящее время более вероятно, что нам придется проходить через каждое всплывающее окно, вручную выработать значение, чтобы настроить удар, и добавить что-то вроде этого каждому:
<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, смотрящее на эту настройку?
Для тех, у кого нет сенсорного устройства, вы можете получить доступ к настройкам планшетного ПК, выполнив:
C:\Windows\explorer.exe shell: {80F3F1D5-FECA-45F3-BC32-752C152E456E}
И посмотрите, что это делает для себя: -)
Казалось бы, это просто невозможно, поэтому мы прибегаем к MultiDataTrigger в вопросе о компенсации.
Я написал настраиваемое всплывающее окно, которое решает эту проблему: вы можете установить свойство зависимостей 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
Установите его в обычный режим для всего приложения:
FieldInfo fi = typeof(SystemParameters).GetField("_menuDropAlignment",
BindingFlags.NonPublic | BindingFlags.Static);
fi.SetValue(null, false);
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
, когда PlacementMode
- Relative
, AbsolutePoint
, RelativePoint
или MousePoint
. Если вы можете использовать один из других PlacementModes
, вы не будете подвергаться проверке MenuDropAlignment
.
Если вы используете PlacementMode.Custom
, тогда вы также захотите установить Popup.CustomPopupPlacementCallback
на допустимый метод, чтобы предоставить свои всплывающие окна CustomPopupPlacement[]
.
Источник: отражатель