简体   繁体   中英

Binding not working with WPF UserControl

I have a Little problem and don't know where to start looking for the solution. I have this WPF UserControl derived from a TextBox:

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;
    }
}

Is a textbox with a input mask. It Works fine. The only thing that is not working is the bindings. I use this control like this:

<local:MaskedTextBox Text="{Binding Path=myProp}" PromptChar=" " InputMask="0000000"></local:MaskedTextBox>

But the value from the property is not show. If I change my control with a normal textbox like this:

<TextBox Text="{Binding Path=myProp}"></TextBox>

It Works just fine. I'm obviously missing something here. I'm not getting bindings erroros.

In the SetText method you are setting the Text property of the TextBox , this will replace the Binding with a string value.

You could update it like this, but I don't know if it is the best way:

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();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM