【问题标题】:WPF TextBox Extension unable to use MahApps TextBoxHelperWPF TextBox Extension 无法使用 MahApps TextBoxHelper
【发布时间】:2017-11-22 13:10:51
【问题描述】:

我有一个扩展的 wpf 文本框,我想使用 MahApps TextBoxHelper 添加水印。使用常规文本框效果很好,但是当我尝试用我的扩展文本框 TouchTextBox 替换它们时,水印随着 Metro 风格消失了。我的扩展文本框旨在与自定义触摸键盘一起使用,并且它具有许多旨在处理此功能的事件:

XAML:

<TextBox x:Class="MyNamespaceHERE.TouchTextBox"
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
     xmlns:local="clr-namespace:MyNamespaceHERE"
     mc:Ignorable="d" 
     GotFocus="TouchTextBox_GotFocus"
     LostFocus="TouchTextBox_LostFocus">
</TextBox>

代码背后:

public partial class TouchTextBox : TextBox
{

    public TouchTextBox()
    {
        InitializeComponent();

    }

    private void TouchTextBox_GotFocus(object sender, RoutedEventArgs e)
    {
        StaticEvents.OnShowTouchKeyboard(sender, e);
        StaticEvents.TouchKeyboardKeyTouch += StaticEvents_TouchKeyboardKeyTouch;
        StaticEvents.TouchKeyboardSpaceTouch += StaticEvents_TouchKeyboardSpaceTouch;
        StaticEvents.TouchKeyboardBackspaceTouch += StaticEvents_TouchKeyboardBackspaceTouch;
    }

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

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

    private void StaticEvents_TouchKeyboardKeyTouch(object sender, EventArgs e)
    {
        int i = CaretIndex;
        string t = (sender as Button).Content.ToString();
        Text = Text.Insert(CaretIndex, t);
        CaretIndex = i + 1;
    }

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

我遵循了我在这个解决方案here 中找到的建议,但到目前为止它还没有解决这个问题。根据解决方案,我需要添加一个基于 TextBox 的样式,所以这是我的资源字典中的内容:

<Style TargetType="local:TouchTextBox" BasedOn="{StaticResource {x:Type TextBox}}" x:Key="TouchTextBoxStyle"/>

我将这种样式添加到我的 TouchTextBox 控件的每个实例中,使它们看起来像这样:

<local:TouchTextBox x:Name="UsernameTextBox" Controls:TextBoxHelper.Watermark="Username" Width="200" Text="{Binding Username}" Style="{StaticResource TouchTextBoxStyle}"/>
<local:TouchTextBox x:Name="PasswordTextBox" Controls:TextBoxHelper.Watermark="Password" Width="200" Margin="0,30,0,0" Text="{Binding Password}" Style="{StaticResource TouchTextBoxStyle}"/>

到目前为止还没有运气。如何使用我的自定义 TouchTextBox 用户控件恢复 MahApps 的 TextBoxHelper 的所有强大功能?非常感谢您提供的任何指导。

编辑:

我采纳了 Joel Lucsy 的建议并实施了一个 TouchTextBoxHelper 类来处理 DependencyProperty 以进行我的事件处理:

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);
        TextBox tb = obj as TextBox;
        if (tb == null) return;
        if (value)
        {

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

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

这有点可怕,但它确实有效!

【问题讨论】:

    标签: c# wpf xaml mvvm mahapps.metro


    【解决方案1】:

    与其创建自定义控件,不如创建一个 DependencyProperty,类似于 TextBoxHelper 将事件添加到普通 TextBox 的方式。这也将消除对样式的需求。

    【讨论】:

    【解决方案2】:

    我认为您需要将此 Attached Properties 添加到 TextBox 以显示水印。

    controls:TextBoxHelper.Watermark="My Watermark" 
    controls:TextBoxHelper.UseFloatingWatermark="True" // If Needed.
    

    带有TextBox的完整代码。

    <TextBox Height="40" Width="125" MaxLength="15"  
        controls:TextBoxHelper.Watermark="My Watermark" 
        controls:TextBoxHelper.UseFloatingWatermark="True"/>
    

    希望这会有所帮助。

    【讨论】:

    • 我实际上对我的 TouchTextBoxes 的每个实例都做了这个。我已经编辑了帖子以包含 TouchTextBox 的实例。
    • 问题在于,虽然 TextBoxHelper 适用于常规文本框,但当我尝试使用自定义的 TouchTextBox 控件时它会中断。
    • 没有错误,当我从 TextBox 更改为 TouchTextBox 时,我的水印消失了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多