绑定不适用于WPF UserControl

时间:2015-08-19 22:54:52

标签: c# wpf data-binding

我有一点问题,不知道从哪里开始寻找解决方案。 我有这个从TextBox派生的WPF UserControl:

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>

它工作得很好。我在这里显然遗漏了一些东西。我没有得到绑定错误。

1 个答案:

答案 0 :(得分:0)

SetText方法中,您要设置Text的{​​{1}}属性,这会将TextBox替换为字符串值。

你可以像这样更新它,但我不知道它是否是最好的方式:

Binding