2015-08-19 3 views
1

У меня есть небольшая проблема и не знаю, с чего начать искать решение. я это WPF UserControl, полученный из 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> 

Это работает просто отлично. Я, очевидно, что-то пропустил. Я не получаю bindings erroros.

+1

Вы не перезаписать его? Текст = this.Provider.ToDisplayString() ;? SetText() и т. Д.? – SledgeHammer

+0

Ничего себе. Кажется, это правильно! Я проверю это и прокомментирую. Благодаря! – ericpap

ответ

0

В SetText методе вы устанавливающий Text свойства TextBox, это заменит 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(); 
Смежные вопросы