[英]Change custom control's appearance dynamically from its children in WPF
我正在使用InputSimulatorCore NuGet package 創建一個 WPF 觸摸屏鍵盤。我創建了一個Keyboard
自定義控件,它基本上是一個包含多個KeyboardButton
自定義控件的網格。
首先,我創建了一個自定義控件,它可以包含一個圖像和一些文本作為我的KeyboardButton
自定義控件的基礎。
public class ImageTextButton : Button
{
// Constructors
static ImageTextButton() => DefaultStyleKeyProperty.OverrideMetadata(typeof(ImageTextButton), new FrameworkPropertyMetadata(typeof(ImageTextButton)));
// Dependency properties
public string ItemName { ... }
public static readonly DependencyProperty ItemNameProperty = ...;
public virtual ImageSource Source { ... }
public static readonly DependencyProperty SourceProperty = ...;
public double ImageHeight { ... }
public static readonly DependencyProperty ImageHeightProperty = ...;
public double ImageWidth { ... }
public static readonly DependencyProperty ImageWidthProperty = ...;
public Brush EllipseFill { ... }
public static readonly DependencyProperty EllipseFillProperty = ...;
public Brush FontColor { ... }
public static readonly DependencyProperty FontColorProperty = ...;
public static P FindVisualParent<P>(DependencyObject dep) where P : DependencyObject
{
while (dep != null)
{
if ((dep is Visual) || (dep is System.Windows.Media.Media3D.Visual3D))
{
if (dep is P)
{
return (dep as P);
}
dep = VisualTreeHelper.GetParent(dep);
}
else
{
dep = LogicalTreeHelper.GetParent(dep);
}
}
return (null);
}
}
接下來,我像這樣從ImageTextButton
繼承來創建一個基本的KeyboardButton
控件,它可以調用InputSimulator
object 來發送按鍵。
public class KeyboardButton : ImageTextButton
{
protected Keyboard _keyboard;
protected InputSimulator _sim = new InputSimulator();
public ImageSource SourceNormal { ... }
public static readonly DependencyProperty SourceNormalProperty = ...;
public ImageSource SourceShift { ... }
public static readonly DependencyProperty SourceShiftProperty = ...;
public virtual bool Shifted { ... }
public static readonly DependencyProperty ShiftedProperty = ...;
static KeyboardButton() { }
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
this._keyboard = FindVisualParent<Keyboard>(this);
}
}
然后我定義了一個CharacterOutputButton
,它可以發送實際的按鍵操作,就像用戶在鍵盤上鍵入一樣:
public class CharacterOutputButton : KeyboardButton
{
public VirtualKeyCode OutputCode { ... } // From the InputSimulator NuGet
public static readonly DependencyProperty OutputCodeProperty = ...;
public string Output { ... }
public static readonly DependencyProperty OutputProperty = ...;
public string OutputShift { ... }
public static readonly DependencyProperty OutputShiftProperty = ...;
static CharacterOutputButton() { }
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
// Sets the click event, is there a better way to do this?
Click += (s, e) =>
{
_keyboard.Target.Focus();
if (OutputCode > 0)
{
_sim.Keyboard.KeyPress(OutputCode);
}
else
{
_sim.Keyboard.TextEntry(Output);
}
};
}
}
最后,我想實現也繼承自KeyboardButton
的CapsLockKey
自定義控件以切換大寫鎖定:
public class CapsLockKey : KeyboardButton
{
public override ImageSource Source // Update property when it's called?
{
get => NativeMethods.GetKeyState((ushort)VirtualKeyCode.CAPITAL) > 0 ? SourceNormal : SourceShift;
set => base.Source = NativeMethods.GetKeyState((ushort)VirtualKeyCode.CAPITAL) > 0 ? SourceNormal : SourceShift;
}
static CapsLockKey() { }
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
Click += (s, e) =>
{
_sim.Keyboard.KeyPress(VirtualKeyCode.CAPITAL);
if (NativeMethods.GetKeyState((ushort)VirtualKeyCode.CAPITAL) > 0)
{
Source = SourceNormal;
}
else
{
Source = SourceShift;
}
};
}
}
如您所見,我以前嘗試的很多殘余(屬性,如Shift
和Shifted
)在按下 Caps Lock 鍵時實現樣式更改,但無濟於事。
我想我有兩個具體問題:
按下 Caps Lock 時,如何動態更新角色 Output 按鈕的樣式?
如果我更改鍵盤樣式,例如重新排列鍵以匹配不同的鍵盤布局(QWERTY 與 AZERTY),我如何維護此 state
您可以使用VisualStateManager class在控件的不同視覺狀態之間動態轉換:
if (someElement.IsCapsLockPressed)
{
VisualStateManager.GoToElementState(rect, "SomeState", true);
}
else
{
VisualStateManager.GoToElementState(rect, "SomeOtherState", true);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.