C# 将TextChanged函数放入类中以供多个文本框使用

C# 将TextChanged函数放入类中以供多个文本框使用,c#,wpf,C#,Wpf,我有一个应用程序,主要用来捕获数值数据。 通常我使用文本框。为了组织这篇文章,我决定将输入的数字分组,并在分组之间留出空格 所以像“5555555”这样的东西会像“5555555”一样出现,以提供类似whatsapp或viber注册文本框的效果。我正在使用TextChanged事件来完成此操作 这里有一个我到目前为止是如何做到这一点的例子。这是一个用于输入电话号码的文本框 private void cell_TextChanged(object sender, TextChangedEventA

我有一个应用程序,主要用来捕获数值数据。 通常我使用文本框。为了组织这篇文章,我决定将输入的数字分组,并在分组之间留出空格

所以像“5555555”这样的东西会像“5555555”一样出现,以提供类似whatsapp或viber注册文本框的效果。我正在使用TextChanged事件来完成此操作

这里有一个我到目前为止是如何做到这一点的例子。这是一个用于输入电话号码的文本框

private void cell_TextChanged(object sender, TextChangedEventArgs e)
    {
        string phrase = cell.Text;
        if (phrase != null)
        {
            // This is to reset all spaces in the text back to none before the code below puts new ones.
            // This avoids puting a space directly next to another one previously set.
            // For some reason the textbox becomes difficult  to work with if I don't do this.
            phrase = Regex.Replace(phrase, @"\s+", "");
        }

        // If the text is smaller than 4 characters;
        if (phrase.Length <= 4)
        {
            // Do nothing to it
            cell.Text = phrase;
        }

        // if the text is equal to five characters
        if (phrase.Length == 5)
        {
            // group the first 3 characters
            string first = phrase.Substring(0, 3);
            // and the last 2 to characters
            string second = phrase.Substring(3, 2);

            // then put a space between them
            string paste = (first + " " + second);
            //This string goes into the TextBox 'cell'
            cell.Text = paste;
        }

        // if the text is equal to six characters
        if (phrase.Length == 6)
        {
            // group the first 3 characters
            string first = phrase.Substring(0, 3);

            //And the last 3 characters
            string second = phrase.Substring(3, 3);

            // then put a space between them
            string paste = (first + " " + second);
            //This string goes into the TextBox 'cell'
            cell.Text = paste;
        }

        if (phrase.Length == 7)
        {
            // group the first 4 characters
            string first = phrase.Substring(0, 4);
            // then the next 3
            string second = phrase.Substring(4, 3);

            // then put a space between them
            string paste = (first + " " + second);
            //This string goes into the TextBox 'cell'
            cell.Text = paste;
        }

        if (phrase.Length == 8)
        {
            // group the first 4 characters
            string first = phrase.Substring(0, 4);
            // then the next 3
            string second = phrase.Substring(4, 3);
            // then the next character
            string third = phrase.Substring(7, 1);

            // then put a space between the first, second and third string
            string paste = (first + " " + second + " " + third);
            //This string goes into the TextBox 'cell'
            cell.Text = paste;
        }

        if (phrase.Length == 9)
        {
            // group the first 4 characters
            string first = phrase.Substring(0, 4);
            // then the next 3
            string second = phrase.Substring(4, 3);
            // then the next 2 characters
            string third = phrase.Substring(7, 2);

            // then put a space between the first, second and third string
            string paste = (first + " " + second + " " + third);
            //This string goes into the TextBox 'cell'
            cell.Text = paste;
        }

        if (phrase.Length == 10)
        {
            // group the first 4 characters
            string first = phrase.Substring(0, 4);
            // then the next 3
            string second = phrase.Substring(4, 3);
            // then the next 3 characters after that
            string third = phrase.Substring(7, 3);

            // then put a space between the first, second and third string
            string paste = (first + " " + second + " " + third);
            //This string goes into the TextBox 'cell'
            cell.Text = paste;
        }

        //This is to keep the cursor at the end of the TextBox's text when I enter a new character other wise it goes back to the start.
        cell.CaretIndex = cell.Text.Length;
    }
private void cell\u TextChanged(对象发送方,textchangedventargs e)
{
字符串短语=cell.Text;
if(短语!=null)
{
//这是在下面的代码放入新空格之前,将文本中的所有空格重置为无。
//这样可以避免将一个空格直接放在先前设置的另一个空格旁边。
//由于某种原因,如果我不这样做,文本框将变得很难使用。
短语=Regex.Replace(短语@“\s+”,“”);
}
//如果文本小于4个字符;

如果(phrase.Length您应该从
cell_TextChanged
中提取代码,并将其移动到一个新方法中。然后在事件处理程序中调用此新方法

e、 g

这种方法意味着您不必为每个事件编写相同的代码,只需重复使用相同的代码。
YourTextChangedHandlerMethod
的第一个参数是引发事件的文本框


您可能会发现,您可以收紧新方法所采用的参数,但这对您来说应该很简单。

如果您想以MVVM的方式执行此操作,您可以使用以下任何选项:

一,。 绑定到不同的属性并在ViewModel中调用相同的方法。不要忘记指定UpdateSourceTrigger

<TextBox Text="{Binding MyText, ElementName=myControl, UpdateSourceTrigger=PropertyChanged}"/>

2. 或者为文本框编写自己的附加行为,以支持TextChanged命令

三,。 或者使用System.Windows.Interactivity中的InvokeCommandAction绑定到同一方法

<TextBox x:Name="SomeText">
  <interactivity:Interaction.Triggers>
    <interactivity:EventTrigger EventName="TextChanged">
      <interactivity:InvokeCommandAction Command="{Binding SomeCommand, Mode=OneWay}"/>
    </interactivity:EventTrigger>
  </interactivity:Interaction.Triggers>         
</TextBox>

如果您没有遵循MVVM,那么您可以使用类似的方法

class FindingLogicalChildren
{
    public static IEnumerable<T> FindVisualChildren<T>(DependencyObject dependencyObject) where T : DependencyObject
    {
        if (dependencyObject != null)
        {
            for (int i = 0; i < VisualTreeHelper.GetChildrenCount(dependencyObject); i++)
            {
                DependencyObject child = VisualTreeHelper.GetChild(dependencyObject, i);
                if (child != null && child is T)
                {
                    yield return (T)child;
                }

                foreach (T childOfChild in FindVisualChildren<T>(child))
                {
                    yield return childOfChild;
                }
            }

        }

    }
类查找逻辑儿童
{
公共静态IEnumerable FindVisualChildren(DependencyObject DependencyObject),其中T:DependencyObject
{
if(dependencyObject!=null)
{
for(int i=0;i
并在主窗口中加载

mainwindow.xaml

   private void window_Loaded(object sender, RoutedEventArgs e)
    {
      foreach (TextBox it in FindingLogicalChildren.FindVisualChildren<TextBox>(Application.Current.MainWindow))
        {
            t = it;
            t.TextChanged += t_TextChanged;
        }
}

void t_TextChanged(object sender, TextChangedEventArgs e)
    {
      // do your work here.. you get all textchanged events here    
    }
private void window\u已加载(对象发送方,路由目标)
{
foreach(在FindingLogicalChildren.FindVisualChildren(Application.Current.MainWindow)中的文本框)
{
t=它;
t、 TextChanged+=t_TextChanged;
}
}
void t_TextChanged(对象发送方,textchangedventargs e)
{
//在这里做你的工作。你在这里得到所有的文本更改事件
}

将某些代码封装到任何UI控件中的最简单方法是声明附加属性…这正是它们的作用所在-扩展预先存在的UI元素的功能。如果您不熟悉附加属性,则可以从MSDN上的页面了解有关附加属性的更多信息

下面是一个您可以使用的示例…您只需添加事件处理程序:

public static readonly DependencyProperty IsFormattedProperty = DependencyProperty.RegisterAttached("IsFormatted", typeof(bool), typeof(TextBoxProperties), new UIPropertyMetadata(default(bool), OnIsFormattedChanged));

public static bool GetIsFormatted(DependencyObject dependencyObject)
{
    return (bool)dependencyObject.GetValue(IsFormattedProperty);
}

public static void SetIsFormatted(DependencyObject dependencyObject, bool value)
{
    dependencyObject.SetValue(IsFormattedProperty, value);
}

public static void OnIsFormattedChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
{
    TextBox textBox = dependencyObject as TextBox;
    if (textBox != null)
    {
        bool newIsFormattedValue = (bool)dependencyPropertyChangedEventArgs.NewValue;
        if (newIsFormattedValue) textBox.TextChanged += YourTextChangedHandler;
        else textBox.TextChanged -= YourTextChangedHandler;
    }
}
应将其添加到名为
TextBoxProperties
的类中,使用方法如下:

<TextBox TextBoxProperties:IsFormatted="True" ... />


<代码>将代码提取到一个单独的方法中,并从处理程序调用该方法。如果您的需求适合,考虑在MVVM方法中这样做,它也会提高性能。这可能对您有帮助:<代码>为(int i=3;i<s长度;i+=4){s= s插入(s长度-i),“”);}
您希望用户以后自己修改这些分组吗?例如,如果用户备份到一个空格并手动删除它,会发生什么情况?好的,我听到了。问题是,我如何告诉新方法接受来自任何文本框的文本,而不仅仅是cell.text?我如何告诉它应该将字符串“粘贴”返回到textbox触发了它?我只是对答案做了一个小的更新,希望能有所帮助。
sender
参数是引发事件的控件,因此它不关心哪个文本框引发了事件,只关心它正在处理一个文本框。显然,在新方法中,您应该将
cell
重命名为更通用的名称。嗨。Another问题。我如何将“sender”中的值传递给字符串“phrase”?在它是
string phrase=cell.Text
之前。似乎
string phrase=sender
不起作用,
sender.ToString
cast也不起作用……我想我还是不明白。抱歉,如果我问的问题应该是更明显的。我很抱歉当您提到将“cell”重命名为Offer try(发送者为文本框)时,我猜您可能是指这个.Text@DanielKelley我可以确认你的代码是有效的。我刚刚发现Sheridan的代码更容易在以后的其他页面上实现。尽管如此,我还是很感激。如果我没有先弄明白这一点,它就不会起作用了。我想你不需要使用交互性,对于文本更改,你可以在Propertychanged上使用UpdateSourceRigger。你可以使用其中任何一种se三个选项:)。编辑答案。选项2为我做了。谢谢。嗨。如果我可以问一下,我该如何定义事件?我已经尝试了
public void YourTextChangedHandler(object sender,TextChangedEventHandler routedEventArgs)
public void Yo
<TextBox TextBoxProperties:IsFormatted="True" ... />