我有一个Ip地址的TextBoxInputMaskBehavior,如下所示:
和xaml代码:
<UserControl x:Class="Customizing.Views.IpRangeFields"
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:ig="http://schemas.infragistics.com/xaml"
xmlns:local="clr-namespace:Customizing.Views"
xmlns:net="clr-namespace:System.Net;assembly=System"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:behaviors="clr-namespace:Customizing.Behaviors"
xmlns:system="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
x:Name="Uc"
d:DesignHeight="300" d:DesignWidth="300">
<UserControl.Resources>
<system:String x:Key="InputMaskIp">000.000.000.000</system:String>
</UserControl.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="60" />
<RowDefinition Height="10" />
<RowDefinition Height="60" />
<RowDefinition Height="10" />
<RowDefinition Height="60" />
<RowDefinition Height="10" />
<RowDefinition Height="60" />
<RowDefinition Height="10" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="2.5*" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Content="Start" VerticalContentAlignment="Center" FontSize="18"
HorizontalContentAlignment="Center" FontWeight="Bold" />
<Label Grid.Row="2" Grid.Column="0" Content="End" VerticalContentAlignment="Center" FontSize="18"
HorizontalContentAlignment="Center" FontWeight="Bold" />
<Label Grid.Row="4" Grid.Column="0" Content="Subnet" VerticalContentAlignment="Center" FontSize="18"
HorizontalContentAlignment="Center" FontWeight="Bold" />
<Label Grid.Row="6" Grid.Column="0" Content="Gateway" VerticalContentAlignment="Center" FontSize="18"
HorizontalContentAlignment="Center" FontWeight="Bold" />
<TextBox VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Grid.Row="0" Grid.Column="1"
FontSize="22" Validation.Error="_ValidationError">
<TextBox.Text>
<Binding ElementName="Uc" Path="Start" ValidatesOnNotifyDataErrors="True"
UpdateSourceTrigger="PropertyChanged"
NotifyOnValidationError="true">
<Binding.ValidationRules>
<local:IpAddressRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
<i:Interaction.Behaviors>
<behaviors:TextBoxInputMaskBehavior InputMask="{StaticResource InputMaskIp}" PromptChar="0" />
</i:Interaction.Behaviors>
</TextBox>
<TextBox VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Grid.Row="2" Grid.Column="1"
FontSize="22" Validation.Error="_ValidationError">
<Binding ElementName="Uc" Path="End" ValidatesOnNotifyDataErrors="True"
UpdateSourceTrigger="PropertyChanged"
NotifyOnValidationError="true">
<Binding.ValidationRules>
<local:IpAddressRule />
</Binding.ValidationRules>
</Binding>
<i:Interaction.Behaviors>
<behaviors:TextBoxInputMaskBehavior InputMask="{StaticResource InputMaskIp}" PromptChar="0" />
</i:Interaction.Behaviors>
</TextBox>
<TextBox VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Grid.Row="4" Grid.Column="1"
FontSize="22" Validation.Error="_ValidationError">
<TextBox.Text>
<Binding ElementName="Uc" Path="Subnet" ValidatesOnNotifyDataErrors="True"
UpdateSourceTrigger="PropertyChanged"
NotifyOnValidationError="true">
<Binding.ValidationRules>
<local:IpAddressRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
<i:Interaction.Behaviors>
<behaviors:TextBoxInputMaskBehavior InputMask="{StaticResource InputMaskIp}" PromptChar="0" />
</i:Interaction.Behaviors>
</TextBox>
<TextBox VerticalContentAlignment="Center" HorizontalContentAlignment="Center" Grid.Row="6" Grid.Column="1"
FontSize="22" Validation.Error="_ValidationError">
<TextBox.Text>
<Binding ElementName="Uc" Path="Gateway" ValidatesOnNotifyDataErrors="True"
UpdateSourceTrigger="PropertyChanged"
NotifyOnValidationError="true">
<Binding.ValidationRules>
<local:IpAddressRule />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
<i:Interaction.Behaviors>
<behaviors:TextBoxInputMaskBehavior InputMask="{StaticResource InputMaskIp}" PromptChar="0" />
</i:Interaction.Behaviors>
</TextBox>
</Grid>
</UserControl>
和背后的代码:
using System.Globalization;
using System.Net;
using System.Windows;
using System.Windows.Controls;
namespace Customizing.Views
{
/// <summary>
/// Interaction logic for IpRangeFields.xaml
/// </summary>
public partial class IpRangeFields : UserControl
{
public static readonly DependencyProperty StartProperty = DependencyProperty.Register("Start", typeof (string),
typeof (IpRangeFields), new PropertyMetadata(null));
public static readonly DependencyProperty EndProperty = DependencyProperty.Register("End", typeof (string),
typeof (IpRangeFields), new PropertyMetadata(null));
public static readonly DependencyProperty SubnetProperty = DependencyProperty.Register("Subnet", typeof (string),
typeof (IpRangeFields), new PropertyMetadata(null));
public static readonly DependencyProperty GatewayProperty = DependencyProperty.Register("Gateway",
typeof (string),
typeof (IpRangeFields), new PropertyMetadata(null));
// Register the routed event
public static readonly RoutedEvent ErrorEvent =
EventManager.RegisterRoutedEvent("Error", RoutingStrategy.Bubble,
typeof (RoutedEventHandler), typeof (IpRangeFields));
public IpRangeFields()
{
InitializeComponent();
}
public string Start
{
get { return (string) GetValue(StartProperty); }
set { SetValue(StartProperty, value); }
}
public string End
{
get { return (string) GetValue(EndProperty); }
set { SetValue(EndProperty, value); }
}
public string Subnet
{
get { return (string) GetValue(SubnetProperty); }
set { SetValue(SubnetProperty, value); }
}
public string Gateway
{
get { return (string) GetValue(GatewayProperty); }
set { SetValue(GatewayProperty, value); }
}
public event RoutedEventHandler Error
{
add { AddHandler(ErrorEvent, value); }
remove { RemoveHandler(ErrorEvent, value); }
}
private void _ValidationError(object sender, ValidationErrorEventArgs e)
{
RaiseEvent(new RoutedEventArgs(ErrorEvent, sender));
}
}
public class IpAddressRule : ValidationRule
{
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
IPAddress ip;
if (!IPAddress.TryParse(value.ToString(), out ip))
{
return new ValidationResult(false, "IP address is not valid.");
}
return new ValidationResult(true, null);
}
}
}
我的问题就像您在图片上看到的那样,只有子网字段显示值,但其他三个字段没有。
我确定<behaviors:TextBoxInputMaskBehavior InputMask="{StaticResource InputMaskIp}" PromptChar="0" />
掩盖了三个字段的值,因此无法看到这些值 令我困惑的是,为什么子网字段上的值会出现?我在其他三个领域做错了什么?
Textboxmask类:
using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interactivity;
namespace Customizing.Behaviors
{
/// <summary>
/// InputMask for Textbox with 2 Properties: <see cref="InputMask" />, <see cref="PromptChar" />.
/// </summary>
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
}
}
答案 0 :(得分:1)
如果我正在解决这个问题,并且我想要一个带有IP地址的屏蔽文本框,我将自定义附加属性替换为另一家公司,如DevExpress或Telerik。
在我看来,much simpler to use one line of XAML解决了这个问题。
免责声明:我与这两家公司没有任何关系。
答案 1 :(得分:1)
我复制了你的代码,它运行没有错误。
设置值(ipRange是您的控件):
ipRange.Start = "123.456.789.000";
ipRange.End = "123.456.789.000";
ipRange.Subnet = "123.456.789.000";
ipRange.Gateway = "123.456.789.000";
结果:
我认为,绑定或其他问题,但不能控制。
一条评论。将您的掩码从000.000.000.000
更改为000\.000\.000\.000
,因为.
是小数点分隔符(在我的国家/地区,它是逗号,而不是点,因此您可以在文化支持方面遇到麻烦)。