绑定不能与WPF UserControl一起工作
本文关键字:一起 工作 UserControl WPF 不能 绑定 | 更新日期: 2023-09-27 18:08:44
我有一个小问题,不知道从哪里开始寻找解决方案。我有这个WPF用户控件派生自一个文本框:
public class MaskedTextBox : TextBox
{
#region DependencyProperties
public string UnmaskedText
{
get { return (string)GetValue(UnmaskedTextProperty); }
set
{
SetValue(UnmaskedTextProperty, value);
}
}
public static readonly DependencyProperty UnmaskedTextProperty =
DependencyProperty.Register("UnmaskedText", typeof(string),
typeof(MaskedTextBox), new UIPropertyMetadata(""));
public static readonly DependencyProperty InputMaskProperty =
DependencyProperty.Register("InputMask", typeof(string), typeof(MaskedTextBox), null);
public string InputMask
{
get { return (string)GetValue(InputMaskProperty); }
set { SetValue(InputMaskProperty, value); }
}
public static readonly DependencyProperty PromptCharProperty =
DependencyProperty.Register("PromptChar", typeof(char), typeof(MaskedTextBox),
new PropertyMetadata('_'));
public char PromptChar
{
get { return (char)GetValue(PromptCharProperty); }
set { SetValue(PromptCharProperty, value); }
}
#endregion
private MaskedTextProvider Provider;
public MaskedTextBox()
{
Loaded += new RoutedEventHandler(MaskedTextBox_Loaded);
PreviewTextInput += new TextCompositionEventHandler(MaskedTextBox_PreviewTextInput);
PreviewKeyDown += new KeyEventHandler(MaskedTextBox_PreviewKeyDown);
}
void MaskedTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Space)
{
this.TreatSelectedText();
var position = this.GetNextCharacterPosition(SelectionStart, true);
if (this.Provider.InsertAt(" ", position))
this.RefreshText(position);
e.Handled = true;
}
if (e.Key == Key.Back)
{
this.TreatSelectedText();
var position = this.GetNextCharacterPosition(SelectionStart, false);
//e.Handled = true;
if (position > 0)
{
if (position + 1 != SelectionStart)
if (SelectionLength == 0)
position = this.GetNextCharacterPosition(position - 1, false);
if (this.Provider.RemoveAt(position))
{
if (position > 0)
position = this.GetNextCharacterPosition(position, false);
}
}
this.RefreshText(position);
e.Handled = true;
}
if (e.Key == Key.Delete)
{
if (this.TreatSelectedText())
{
this.RefreshText(SelectionStart);
}
else
{
if (this.Provider.RemoveAt(SelectionStart))
this.RefreshText(SelectionStart);
}
e.Handled = true;
}
}
void MaskedTextBox_PreviewTextInput(object sender, TextCompositionEventArgs e)
{
this.TreatSelectedText();
var position = this.GetNextCharacterPosition(SelectionStart, true);
if (Keyboard.IsKeyToggled(Key.Insert))
{
if (this.Provider.Replace(e.Text, position))
position++;
}
else
{
if (this.Provider.InsertAt(e.Text, position))
position++;
}
position = this.GetNextCharacterPosition(position, true);
this.RefreshText(position);
e.Handled = true;
}
void MaskedTextBox_Loaded(object sender, RoutedEventArgs e)
{
this.Provider = new MaskedTextProvider(InputMask, CultureInfo.CurrentCulture);
if (String.IsNullOrWhiteSpace(UnmaskedText))
this.Provider.Set(String.Empty);
else
this.Provider.Set(UnmaskedText);
this.Provider.PromptChar = PromptChar;
Text = this.Provider.ToDisplayString();
var textProp = DependencyPropertyDescriptor.FromProperty(MaskedTextBox.TextProperty, typeof(MaskedTextBox));
if (textProp != null)
{
textProp.AddValueChanged(this, (s, args) => this.UpdateText());
}
DataObject.AddPastingHandler(this, Pasting);
}
private void Pasting(object sender, DataObjectPastingEventArgs e)
{
if (e.DataObject.GetDataPresent(typeof(string)))
{
var pastedText = (string)e.DataObject.GetData(typeof(string));
this.TreatSelectedText();
var position = GetNextCharacterPosition(SelectionStart, true);
if (this.Provider.InsertAt(pastedText, position))
{
this.RefreshText(position);
}
}
e.CancelCommand();
}
private void UpdateText()
{
if (this.Provider.ToDisplayString().Equals(Text))
return;
var success = this.Provider.Set(Text);
this.SetText(success ? this.Provider.ToDisplayString() : Text, this.Provider.ToString(false, false));
}
private bool TreatSelectedText()
{
if (SelectionLength > 0)
{
return this.Provider.RemoveAt(SelectionStart,
SelectionStart + SelectionLength - 1);
}
return false;
}
private void RefreshText(int position)
{
SetText(this.Provider.ToDisplayString(), this.Provider.ToString(false, false));
SelectionStart = position;
}
private void SetText(string text, string unmaskedText)
{
UnmaskedText = String.IsNullOrWhiteSpace(unmaskedText) ? null : unmaskedText;
Text = String.IsNullOrWhiteSpace(text) ? null : text;
}
private int GetNextCharacterPosition(int startPosition, bool goForward)
{
var position = this.Provider.FindEditPositionFrom(startPosition, goForward);
if (position == -1)
return startPosition;
else
return position;
}
}
是一个带有输入掩码的文本框。它很好用。唯一不能工作的是绑定。我像这样使用这个控件:
<local:MaskedTextBox Text="{Binding Path=myProp}" PromptChar=" " InputMask="0000000"></local:MaskedTextBox>
但是没有显示属性的值。如果我用一个普通的文本框来改变控件,像这样:
<TextBox Text="{Binding Path=myProp}"></TextBox>
It Works just fine。我显然漏掉了什么。我没有得到绑定错误
在SetText
方法中,您正在设置TextBox
的Text
属性,这将用字符串值替换Binding
。
你可以这样更新,但我不知道这是不是最好的方式:
var binding = BindingOperations.GetBindingExpression(this, TextBox.TextProperty);
PropertyInfo property = binding.DataItem.GetType().GetProperty(binding.ParentBinding.Path.Path);
if (property != null)
property.SetValue(binding.DataItem, String.IsNullOrWhiteSpace(text) ? null : text, null);
binding.UpdateTarget();