绑定不能与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。我显然漏掉了什么。我没有得到绑定错误

绑定不能与WPF UserControl一起工作

SetText方法中,您正在设置TextBoxText属性,这将用字符串值替换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();