C# TextBoxInputMask避免空格

C# TextBoxInputMask避免空格,c#,xaml,C#,Xaml,我正在尝试构建IP地址inputboxmask,如下所示: 我不喜欢的是数字之间的空格。我的问题是,如何防止数字之间出现空格,并强制用户写一个数字,而不是留下空格 行为类 public class TextBoxInputMaskBehavior : Behavior<TextBox> { public MaskedTextProvider Provider { get; private set; } protected override

我正在尝试构建IP地址inputboxmask,如下所示:

我不喜欢的是数字之间的空格。我的问题是,如何防止数字之间出现空格,并强制用户写一个数字,而不是留下空格

行为类

public class TextBoxInputMaskBehavior : Behavior<TextBox>
    {
        public MaskedTextProvider Provider { get; private set; }

        protected override void OnAttached()
        {
            base.OnAttached();
            AssociatedObject.Loaded += AssociatedObjectLoaded;
            AssociatedObject.PreviewTextInput += AssociatedObjectPreviewTextInput;
            AssociatedObject.PreviewKeyDown += AssociatedObjectPreviewKeyDown;

            DataObject.AddPastingHandler(AssociatedObject, Pasting);
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();
            AssociatedObject.Loaded -= AssociatedObjectLoaded;
            AssociatedObject.PreviewTextInput -= AssociatedObjectPreviewTextInput;
            AssociatedObject.PreviewKeyDown -= AssociatedObjectPreviewKeyDown;

            DataObject.RemovePastingHandler(AssociatedObject, Pasting);
        }

        /*
        Mask Character  Accepts  Required?  
        0  Digit (0-9)  Required  
        9  Digit (0-9) or space  Optional  
        #  Digit (0-9) or space  Required  
        L  Letter (a-z, A-Z)  Required  
        ?  Letter (a-z, A-Z)  Optional  
        &  Any character  Required  
        C  Any character  Optional  
        A  Alphanumeric (0-9, a-z, A-Z)  Required  
        a  Alphanumeric (0-9, a-z, A-Z)  Optional  
           Space separator  Required 
        .  Decimal separator  Required  
        ,  Group (thousands) separator  Required  
        :  Time separator  Required  
        /  Date separator  Required  
        $  Currency symbol  Required  

        In addition, the following characters have special meaning:

        Mask Character  Meaning  
        <  All subsequent characters are converted to lower case  
        >  All subsequent characters are converted to upper case  
        |  Terminates a previous < or >  
        \  Escape: treat the next character in the mask as literal text rather than a mask symbol  

        */

        private void AssociatedObjectLoaded(object sender, RoutedEventArgs e)
        {
            Provider = new MaskedTextProvider(InputMask, CultureInfo.CurrentCulture);
            Provider.Set(AssociatedObject.Text);
            Provider.PromptChar = PromptChar;
            AssociatedObject.Text = Provider.ToDisplayString();

            //seems the only way that the text is formatted correct, when source is updated
            var textProp = DependencyPropertyDescriptor.FromProperty(TextBox.TextProperty, typeof (TextBox));
            if (textProp != null)
            {
                textProp.AddValueChanged(AssociatedObject, (s, args) => UpdateText());
            }
        }

        private void AssociatedObjectPreviewTextInput(object sender, TextCompositionEventArgs e)
        {
            TreatSelectedText();

            var position = GetNextCharacterPosition(AssociatedObject.SelectionStart);

            if (Keyboard.IsKeyToggled(Key.Insert))
            {
                if (Provider.Replace(e.Text, position))
                    position++;
            }
            else
            {
                if (Provider.InsertAt(e.Text, position))
                    position++;
            }

            position = GetNextCharacterPosition(position);

            RefreshText(position);

            e.Handled = true;
        }

        private void AssociatedObjectPreviewKeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Space) //handle the space
            {
                TreatSelectedText();

                var position = GetNextCharacterPosition(AssociatedObject.SelectionStart);

                if (Provider.InsertAt(" ", position))
                    RefreshText(position);

                e.Handled = true;
            }

            if (e.Key == Key.Back) //handle the back space
            {
                if (TreatSelectedText())
                {
                    RefreshText(AssociatedObject.SelectionStart);
                }
                else
                {
                    if (AssociatedObject.SelectionStart != 0)
                    {
                        if (Provider.RemoveAt(AssociatedObject.SelectionStart - 1))
                            RefreshText(AssociatedObject.SelectionStart - 1);
                    }
                }

                e.Handled = true;
            }

            if (e.Key == Key.Delete) //handle the delete key
            {
                //treat selected text
                if (TreatSelectedText())
                {
                    RefreshText(AssociatedObject.SelectionStart);
                }
                else
                {
                    if (Provider.RemoveAt(AssociatedObject.SelectionStart))
                        RefreshText(AssociatedObject.SelectionStart);
                }

                e.Handled = true;
            }
        }

        /// <summary>
        ///     Pasting prüft ob korrekte Daten reingepastet werden
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Pasting(object sender, DataObjectPastingEventArgs e)
        {
            if (e.DataObject.GetDataPresent(typeof (string)))
            {
                var pastedText = (string) e.DataObject.GetData(typeof (string));

                TreatSelectedText();

                var position = GetNextCharacterPosition(AssociatedObject.SelectionStart);

                if (Provider.InsertAt(pastedText, position))
                {
                    RefreshText(position);
                }
            }

            e.CancelCommand();
        }

        private void UpdateText()
        {
            //check Provider.Text + TextBox.Text
            if (Provider.ToDisplayString().Equals(AssociatedObject.Text))
                return;

            //use provider to format
            var success = Provider.Set(AssociatedObject.Text);

            //ui and mvvm/codebehind should be in sync
            SetText(success ? Provider.ToDisplayString() : AssociatedObject.Text);
        }

        /// <summary>
        ///     Falls eine Textauswahl vorliegt wird diese entsprechend behandelt.
        /// </summary>
        /// <returns>true Textauswahl behandelt wurde, ansonsten falls </returns>
        private bool TreatSelectedText()
        {
            if (AssociatedObject.SelectionLength > 0)
            {
                return Provider.RemoveAt(AssociatedObject.SelectionStart,
                    AssociatedObject.SelectionStart + AssociatedObject.SelectionLength - 1);
            }
            return false;
        }

        private void RefreshText(int position)
        {
            SetText(Provider.ToDisplayString());
            AssociatedObject.SelectionStart = position;
        }

        private void SetText(string text)
        {
            AssociatedObject.Text = string.IsNullOrWhiteSpace(text) ? string.Empty : text;
        }

        private int GetNextCharacterPosition(int startPosition)
        {
            var position = Provider.FindEditPositionFrom(startPosition, true);

            if (position == -1)
                return startPosition;
            return position;
        }

        #region DependencyProperties

        public static readonly DependencyProperty InputMaskProperty =
            DependencyProperty.Register("InputMask", typeof (string), typeof (TextBoxInputMaskBehavior), null);

        public string InputMask
        {
            get { return (string) GetValue(InputMaskProperty); }
            set { SetValue(InputMaskProperty, value); }
        }

        public static readonly DependencyProperty PromptCharProperty =
            DependencyProperty.Register("PromptChar", typeof (char), typeof (TextBoxInputMaskBehavior),
                new PropertyMetadata('_'));

        public char PromptChar
        {
            get { return (char) GetValue(PromptCharProperty); }
            set { SetValue(PromptCharProperty, value); }
        }

        #endregion
    }
公共类TextBoxInputMaskBehavior:行为
{
公共掩码TextProvider提供程序{get;private set;}
受保护的覆盖无效附加()
{
base.onatached();
AssociatedObject.Loaded+=AssociatedObjectLoaded;
AssociatedObject.PreviewTestInput+=AssociatedObjectPreviewTestInput;
AssociatedObject.PreviewKeyDown+=AssociatedObjectPreviewKeyDown;
AddPastingHandler(关联对象,粘贴);
}
附加时受保护的覆盖无效()
{
base.OnDetaching();
AssociatedObject.Loaded-=AssociatedObjectLoaded;
AssociatedObject.PreviewTestInput-=AssociatedObjectPreviewTestInput;
AssociatedObject.PreviewKeyDown-=AssociatedObjectPreviewKeyDown;
RemovePastingHandler(关联对象,粘贴);
}
/*
是否需要掩码字符?
需要0位数字(0-9)
9位(0-9)或空格可选
#需要数字(0-9)或空格
需要字母(a-z,a-z)
?字母(a-z,a-z)可选
&需要任何字符
C任意字符可选
需要字母数字(0-9,A-z,A-z)
字母数字(0-9,a-z,a-z)可选
需要空间分隔符
.需要小数点分隔符
,需要组(千)分隔符
:需要时间分隔符
/需要日期分隔符
需要$货币符号
此外,以下字符具有特殊含义:
掩码字符含义
<所有后续字符都转换为小写
>所有后续字符都转换为大写
|终止以前的<或>
\转义:将掩码中的下一个字符视为文字文本,而不是掩码符号
*/
已加载关联对象的私有void(对象发送方,RoutedEventArgs e)
{
Provider=新的MaskedTextProvider(InputMask,CultureInfo.CurrentCulture);
Provider.Set(AssociatedObject.Text);
Provider.PromptChar=PromptChar;
AssociatedObject.Text=Provider.ToDisplayString();
//在更新源代码时,似乎是文本格式正确的唯一方法
var textProp=dependencPropertyDescriptor.FromProperty(TextBox.TextProperty,typeof(TextBox));
如果(textProp!=null)
{
textProp.AddValueChanged(AssociatedObject,(s,args)=>UpdateText());
}
}
私有void AssociatedObjectPreviewTestInput(对象发送者,TextCompositionEventArgs e)
{
TreatSelectedText();
var position=GetNextCharacterPosition(AssociatedObject.SelectionStart);
如果(键盘.IsKeyToggled(键.插入))
{
if(提供者替换(如文本、位置))
位置++;
}
其他的
{
if(提供者插入(如文本、位置))
位置++;
}
位置=GetNextCharacterPosition(位置);
刷新文本(位置);
e、 已处理=正确;
}
private void AssociatedObjectPreviewKeyDown(对象发送方,KeyEventArgs e)
{
if(e.Key==Key.Space)//处理空格
{
TreatSelectedText();
var position=GetNextCharacterPosition(AssociatedObject.SelectionStart);
if(Provider.InsertAt(“,位置))
刷新文本(位置);
e、 已处理=正确;
}
if(e.Key==Key.Back)//处理Back空间
{
如果(TreatSelectedText())
{
刷新文本(AssociatedObject.SelectionStart);
}
其他的
{
如果(AssociatedObject.SelectionStart!=0)
{
if(Provider.RemoveAt(AssociatedObject.SelectionStart-1))
刷新文本(AssociatedObject.SelectionStart-1);
}
}
e、 已处理=正确;
}
if(e.Key==Key.Delete)//处理Delete键
{
//处理所选文本
如果(TreatSelectedText())
{
刷新文本(AssociatedObject.SelectionStart);
}
其他的
{
if(Provider.RemoveAt(AssociatedObject.SelectionStart))
刷新文本(AssociatedObject.SelectionStart);
}
e、 已处理=正确;
}
}
/// 
///粘贴prüft ob korrekte Daten reingpaste werden
/// 
/// 
/// 
私有无效粘贴(对象发送方、DataObjectPastingEventArgs e)
{
if(e.DataObject.GetDataPresent(typeof(string)))
{
var pastedText=(string)e.DataObject.GetData(typeof(string));
TreatSelectedText();
var position=GetNextCharacterPosition(AssociatedObject.SelectionStart);
if(提供者插入(粘贴文本,位置))
{
刷新文本(位置);
}
}
e、 取消命令();
}
私有void UpdateText()
{
//选中Provider.Text+TextBox.Text
if(Provider.ToDisplayString
<TextBox VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Grid.Row="6" Grid.Column="1" FontSize="22" >
            <i:Interaction.Behaviors>
                <behaviors:TextBoxInputMaskBehavior InputMask="{StaticResource InputMaskIp}" PromptChar="_" />
            </i:Interaction.Behaviors>
        </TextBox>