【问题标题】:Assigning TextBox object reference to static event handler callback using Dependency Properties使用依赖属性将 TextBox 对象引用分配给静态事件处理程序回调
【发布时间】:2017-11-22 04:55:10
【问题描述】:

我可能把自己画到了一个角落里。我有一个自定义触摸键盘用户控件,它使用静态事件在焦点对准时将按键传递给文本框。我正在尝试为所有文本框创建一个依赖属性,以便在它们处于焦点时订阅我的触摸键盘事件处理程序,并在它们失去焦点时取消订阅。

我目前的问题是PropertyChangedCallbackIsTouchKeyboardTargetChanged 永远不会触发。我读过这是因为它是在 XAML 中设置的,因此永远不会“改变”。

到目前为止,我发现的其他答案都没有完全适用于我的模式。我什至不确定这是否是解决此问题的正确方法,但如果这样做对我来说将非常方便。我按照示例将我的 MahApp 设置为 TextBoxHelper

如果有人可以帮助我解决 PropertyChangedCallback 问题,或者如果有人对如何在任何和所有文本框触发焦点事件时完成订阅/取消订阅静态事件有更好的了解,我将不胜感激。

CS

public class TouchTextBoxHelper : DependencyObject
{
    public static readonly DependencyProperty IsTouchKeyboardTargetProperty = DependencyProperty.Register("IsTouchKeyboardTarget", typeof(bool), typeof(TouchTextBoxHelper), new FrameworkPropertyMetadata(false, IsTouchKeyboardTargetChanged));


    [AttachedPropertyBrowsableForType(typeof(TextBox))]
    public static bool GetIsTouchKeyboardTargetEnabled(DependencyObject obj)
    {
        return (bool)obj.GetValue(IsTouchKeyboardTargetProperty);
    }

    [AttachedPropertyBrowsableForType(typeof(TextBox))]
    public static void SetIsTouchKeyboardTargetEnabled(DependencyObject obj, bool value)
    {
        obj.SetValue(IsTouchKeyboardTargetProperty, value);
    }

    private static void IsTouchKeyboardTargetChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var tb = d as TextBox;
        if (null == tb)
        {
            throw new InvalidOperationException("The property 'IsTouchKeyboardTarget' may only be set on TextBox elements.");
        }

        if (e.OldValue != e.NewValue)
        {
            //tb.SetValue(SpellCheck.IsEnabledProperty, (bool)e.NewValue);
            if ((bool)e.NewValue)
            {
                tb.GotFocus += TextBoxBaseGotFocus;
                tb.LostFocus += TextBoxBaseLostFocus;
            }
            else
            {
                tb.GotFocus -= TextBoxBaseGotFocus;
                tb.LostFocus -= TextBoxBaseLostFocus;
            }
        }
    }

    private static void TextBoxBaseGotFocus(object sender, RoutedEventArgs e)
    {
        TouchTextBoxEvents.tb = sender as TextBox;
        StaticEvents.OnShowTouchKeyboard(sender, e);
        StaticEvents.TouchKeyboardKeyTouch += TouchTextBoxEvents.StaticEvents_TouchKeyboardKeyTouch;
        StaticEvents.TouchKeyboardSpaceTouch += TouchTextBoxEvents.StaticEvents_TouchKeyboardSpaceTouch;
        StaticEvents.TouchKeyboardBackspaceTouch += TouchTextBoxEvents.StaticEvents_TouchKeyboardBackspaceTouch;
    }

    private static void TextBoxBaseLostFocus(object sender, RoutedEventArgs e)
    {
        StaticEvents.OnHideTouchKeyboard(sender, e);
        StaticEvents.TouchKeyboardKeyTouch -= TouchTextBoxEvents.StaticEvents_TouchKeyboardKeyTouch;
        StaticEvents.TouchKeyboardSpaceTouch -= TouchTextBoxEvents.StaticEvents_TouchKeyboardSpaceTouch;
        StaticEvents.TouchKeyboardBackspaceTouch -= TouchTextBoxEvents.StaticEvents_TouchKeyboardBackspaceTouch;
    }
}

public class TouchTextBoxEvents
{
    public static TextBox tb = null;
    public static void StaticEvents_TouchKeyboardKeyTouch(object sender, EventArgs e)
    {
        int i = tb.CaretIndex;
        string t = (sender as Button).Content.ToString();
        tb.Text = tb.Text.Insert(tb.CaretIndex, t);
        tb.CaretIndex = i + 1;
    }

    public static void StaticEvents_TouchKeyboardBackspaceTouch(object sender, EventArgs e)
    {
        int i = tb.CaretIndex;
        if (tb.CaretIndex == 0) return;
        tb.Text = tb.Text.Remove(tb.CaretIndex - 1, 1);
        tb.CaretIndex = i - 1;
    }

    public static void StaticEvents_TouchKeyboardSpaceTouch(object sender, EventArgs e)
    {
        int i = tb.CaretIndex;
        tb.Text = tb.Text.Insert(tb.CaretIndex, " ");
        tb.CaretIndex = i + 1;
    }
}

编辑:

事实证明,我所要做的就是更新我的 setter:

    [AttachedPropertyBrowsableForType(typeof(TextBox))]
    public static void SetIsTouchKeyboardTargetEnabled(DependencyObject obj, bool value)
    {
        obj.SetValue(IsTouchKeyboardTargetProperty, value);
        TextBox tb = obj as TextBox;
        if (tb == null) return;
        if (value)
        {

            tb.GotFocus += TextBoxBaseGotFocus;
            tb.LostFocus += TextBoxBaseLostFocus;
        }
        else
        {
            tb.GotFocus -= TextBoxBaseGotFocus;
            tb.LostFocus -= TextBoxBaseLostFocus;
        }
    }

编辑2:

PropertyChangedCallback 逻辑放入setter 实在是太糟糕了。幸运的是,Clemens 提供了一些很好的建议来使用 RegisterAttached 而不是 Register。这消除了从 DependencyObject 派生的需要,并解决了 PropertyChangedCallback 未触发的问题。

【问题讨论】:

  • 如果这应该是附加属性,您应该使用RegisterAttached 而不是Register。另请注意,TouchTextBoxHelper 不需要从 DependencyObject 派生。
  • 感谢您的建议!这解决了我所有的问题。我希望你能把它放在一个答案中,这样我就可以给你代表和全部。

标签: c# wpf xaml dependency-properties


【解决方案1】:

必须通过调用DependencyProperty.RegisterAttached 而不是Register 来注册附加属性。也不需要从 DependencyObject 派生声明类:

public class TouchTextBoxHelper
{
    public static readonly DependencyProperty IsTouchKeyboardTargetProperty =
        DependencyProperty.RegisterAttached(
            "IsTouchKeyboardTarget",
            typeof(bool),
            typeof(TouchTextBoxHelper),
            new FrameworkPropertyMetadata(false, IsTouchKeyboardTargetChanged));

    ...
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-22
    • 1970-01-01
    • 1970-01-01
    • 2017-12-04
    • 1970-01-01
    • 2018-03-12
    • 1970-01-01
    • 2013-10-09
    相关资源
    最近更新 更多