簡體   English   中英

從 WPF 中的子項動態更改自定義控件的外觀

[英]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);
            }
        };
    }
}

最后,我想實現也繼承自KeyboardButtonCapsLockKey自定義控件以切換大寫鎖定:

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

如您所見,我以前嘗試的很多殘余(屬性,如ShiftShifted )在按下 Caps Lock 鍵時實現樣式更改,但無濟於事。

我想我有兩個具體問題:

  1. 按下 Caps Lock 時,如何動態更新角色 Output 按鈕的樣式?

  2. 如果我更改鍵盤樣式,例如重新排列鍵以匹配不同的鍵盤布局(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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM