2009-10-30 3 views
7

У меня есть пользовательский элемент управления, который я использую внутри DataTemplate, это UserControl содержит TextBox который переплетен с Value имущества (объявленное как DependencyProperty) мой UserControl. В шаблоне данных я связываю это Значение недвижимость с моим фактическим свойством сказать Название (также DependencyProperty). Он корректно работает, я присваиваю значение . Название свойство во время загрузки и мой TextBox отображает его, я меняю значение с TextBox, и он обновляет мое . Идентификационное имя. Теперь проблема возникает, когда я добавляю PropertyChangedEventHandler в свойство зависимости, проверяю значение, если оно действительно, ничего не делайте, если оно действительное, и присваивайте старое значение, если оно недействительно. Если значение недействительно, когда я назначаю ему это старое значение, обновляет свойство, но оно не отображает обновленное значение в моем TextBox из UserControl. Может ли кто-нибудь сказать мне, почему?WPF: TextBox Текст не обновляя

XAML моего UserControl:

<UserControl x:Name="usercontrol"> 
    <StackPanel> 
     <TextBlock ......./> 
     <TextBox Binding={Binding ElementName=usercontrol, Path=Value, Mode=TwoWay}/> 
    </StackPanel> 
</UserControl> 

В коде позади Value является DependencyProperty

Я использую это в моем DataTemplate:

<HierarchicalDataTemplate DataType="{x:Type myLib:myClass}" ItemsSource="{Binding Children}"> 
    <Expander Header="{Binding}"> 
     <WrapPanel> 
      <edproperty:TextPropertyEditor Caption="Name" Value="{Binding Name, Mode=TwoWay}"/> 
      <edproperty:TextPropertyEditor .................../> 
      <edproperty:TextPropertyEditor .................../> 
      <edproperty:TextPropertyEditor ...................../> 
     </WrapPanel> 
    </Expander> 
</HierarchicalDataTemplate> 

Этот шаблон я используя в TreeView. Внутри TreeView я ввожу значение в TextBox который обновляет значение свойство моей UserControl, что в свою очередь, обновляет имя свойство myClass Я назначая PropertyChangedCallback к моему Название собственности в myClass, выполняя некоторые проверки и переназначения OldValue если проверка не выполнена. Он, в свою очередь, обновляет значение . Значение также имеет значение, но я все еще вижу, что значение TextBox имеет то же значение, что я ввел ранее не обновленный.

public string Name 
    { 
     get 
     { 
      return (string)GetValue(NameProperty); 
     } 
     set 
     { 
      SetValue(NameProperty, value); 
     } 
    } 

    // Using a DependencyProperty as the backing store for Name. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty NameProperty = 
     DependencyProperty.Register("Name", typeof(string), typeof(myClass), new UIPropertyMetadata(null, OnNameChanged)); 

    protected static void OnNameChanged(DependencyObject sender, DependencyPropertyChangedEventArgs args) 
    { 
     if(checkRequired && !IsValid(e.NewValue.ToString())) 
     { 
      checkRequired=false; 
      (sender as myClass).Name = args.OldValue.ToString(); 
     } 
    } 

    private static bool IsValid(string name) 
    { 
     .............some logic here 
    } 
+2

Не видя своего кода, это будет трудным для правильного комментирования. Не могли бы вы разместить свой код, пожалуйста? –

+0

это слишком много, его нельзя опубликовать. Вы можете спросить, хотите ли вы больше объяснений. – viky

+2

Нет, вы можете написать минимальный фрагмент кода для воспроизведения ... В противном случае мы будем гадать, а не отвечать. Никто не любит неопределенность. Особенно программисты .. – Anvaka

ответ

7

После нескольких дней озираясь и много поисков я нашел решение моей проблемы

После того как все проверки сделаны, назначаемую и старое значение и обновляя свойство зависимых пакетов, мне нужно кал метода UpdateTarget(), чтобы обновить значение в моем текстовом поле.

Это то, что объясняет решение лучше

http://social.msdn.microsoft.com/forums/en-US/wpf/thread/c404360c-8e31-4a85-9762-0324ed8812ef/

+0

Спасибо! Вы спасли мою жизнь!! –

0

Похоже, вы нарушаете привязку, когда вы устанавливаете значение свойства непосредственно из кода позади.

Вы не должны изменять свойство таким образом. Используйте value coercion mechanism и подтвердите ввод в обратном вызове значения Coerce.

+0

Я тоже использовал этот способ, но все тот же вопрос, значение моего текстового поля не обновляется. – viky

+0

i hav обновил мой вопрос, может ли вы предложить мне что-нибудь? Извините за задержку – viky

0

Анураг,

Есть много предположений, которые я должен сделать, но я дам ему выстрелили.

Вы, наверное, есть что-то вроде этого ...

// ... 
public static string GetValue(Dependency obj) 
{ 
    // ... 
} 

// ... 
public static void SetValue(DependencyObject obj, string value) 
{ 
    // ... 
} 

// Using a DependencyProperty as the backing store for Value. This enables animation, styling, binding, etc... 
public static readonly DependencyProperty ValueProperty = 
    DependencyProperty.RegisterAttached("Value", typeof(string), typeof(MyCustomControl), new UIPropertyMetadata(OnValuePropertyChanged)); 

public static void OnValuePropertyChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) 
{ 
    string newValue = e.NewValue as string; 

    // You validate your value here, 
    // Then if fails, revert to old value. 
    if(!SomeCondtion(newValue)) SetValue(obj,e.OldValue as string); 

} 

Это, безусловно, не самый лучший подход для проверки данных. Существуют и другие, более эффективные подходы, которые обеспечат вам большую гибкость.

  1. Примените правило ValidationRule на своем TexBox.Это моя первая рекомендация, потому что это даст вам контроль над отображением ошибки при неудачной проверке. Если вы после простой проверки, проверьте мой article.
  2. Слушайте событие TextBox.TextChanged. Это громоздко и не может быть использовано повторно для большинства взломанных.
  3. Не используйте метод обратного вызова DependecyPropertyChanged. Используйте зарегистрированную строку Свойство и в своем сеттере, примените логику, например.

    public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(string), typeof(UserControlWithTextBox)); 
    
    
    private string _oldValue; 
    public string Value 
    { 
        get { return GetValue(ValueProperty) as string; } 
        set 
        { 
         // Check if the value passes your validation logic 
         if(SomeCondtion(value)) 
         { 
          // If yes, then set the value, and record down the old value. 
          SetValue(ValueProperty, value); 
          _oldValue = value; 
         } 
         else 
         { 
          // Else logic fails, set the value to old value. 
          SetValue(ValueProperty, _oldValue); 
         } 
         // Implement INotifyPropertyChanged to update the TextBox. 
         if(PropertyChanged != null) 
          PropertyChanged(this, new PropertyChangedEventArgs("Value")); 
        } 
    } 
    

Еще раз, как вы можете видеть из моего ответа, что вы все еще можете показать код в вашем вопросе, чтобы помочь другим не ответить на ваш вопрос, независимо от того, насколько сложным может быть ваше решение (если вы хотите получить хороший ответ , вам нужно приложить усилия, чтобы задать хороший вопрос). Мой ответ может не сработать для вас, но, возможно, он может дать вам несколько направлений «Googling». Надеюсь, поможет.

+0

i hav обновил мой вопрос, извините за задержку Почему это происходит с моим текстовым полем? – viky

+0

Валидация, добавленная в установщик в вашем примере, не будет возникать, когда WPF обновляет свойство через привязку или сеттер или через другие такие механизмы. При использовании свойств зависимостей рекомендуется никогда ничего не помещать в ваших аксессуарах или мутаторах. – jpierson

1

Я знаю, этот вопрос был о TextBox, но для RichTextBox вы бы использовать UpdateLayout().

rtb.AppendText("Text"); 
rtb.ScrollToEnd(); 
rtb.UpdateLayout(); 
Смежные вопросы