【发布时间】:2017-11-22 04:55:10
【问题描述】:
我可能把自己画到了一个角落里。我有一个自定义触摸键盘用户控件,它使用静态事件在焦点对准时将按键传递给文本框。我正在尝试为所有文本框创建一个依赖属性,以便在它们处于焦点时订阅我的触摸键盘事件处理程序,并在它们失去焦点时取消订阅。
我目前的问题是PropertyChangedCallback、IsTouchKeyboardTargetChanged 永远不会触发。我读过这是因为它是在 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