2009-10-30 17 views
7

Tengo un control de usuario que estoy usando el interior de un DataTemplate, este contiene una UserControlTextBox que se enganchan con Valor propiedad (declarada como una DependencyProperty) de mi UserControl. En la plantilla de datos enlace esta propiedad Valor con mi propiedad real, por ejemplo, Nombre (también DependencyProperty). Funciona correctamente, asigno un valor a la propiedad Name mientras cargué y mi TextBox lo muestra, cambio el valor de TextBox y también actualiza mi propiedad Name. Ahora el problema surge mientras agrego un PropertyChangedEventHandler en la propiedad de dependencia, verifico el valor si es válido, no hago nada si es válido y asigno el valor anterior si no es válido. En caso de que el valor no sea válido, cuando le asigno ese valor anterior, la propiedad se actualiza pero no muestra el valor actualizado en mi TextBox de UserControl. puede alguien decirme por que?WPF: Cuadro de texto texto no se actualiza

XAML de mi UserControl:

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

En código detrás Valor es una DependencyProperty

estoy usando esto en mi 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> 

Esta plantilla soy usando en un TreeView. Dentro TreeView entro valor en el TextBox que actualiza el Valor propiedad de mi UserControl, que en las actualizaciones a su vez Nombre propiedad de myClass voy a asignar un PropertyChangedCallback a mi Nombre Propiedad en myClass, realizar alguna validación y la reasignación de la OldValue si la validación falla A su vez, también actualiza la propiedad Valor, pero aún veo que el TextBox tiene el mismo valor que ingresé antes que el actualizado.

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

Sin ver su código, va a ser difícil comentarlo correctamente. ¿Podrías publicar tu código por favor? –

+0

es demasiado, no se puede publicar. Puedes preguntar si quieres más explicación. – viky

+2

No, puedes escribir un código mínimo para reproducir ... De lo contrario, estaremos adivinando, no respondiendo. A nadie le gusta la incertidumbre. Especialmente los programadores. – Anvaka

Respuesta

7

Después de días de mirar a su alrededor y un montón de búsqueda he encontrado la solución de mi problema

Después de todo validación hecho y la asignación de valor antiguo y la actualización de la propiedad dependecy, i necesidad de cal método UpdateTarget(), para actualizar el valor en mi TextBox.

Esto es lo que explica la mejor solución

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

+0

¡Gracias! ¡¡Me salvaste la vida!! –

0

Parece que está rompiendo el enlace cuando establece el valor de la propiedad directamente desde el código.

No debe modificar la propiedad de esa manera. Use value coercion mechanism y valide la entrada en la devolución de llamada del valor de coerción.

+0

utilicé esta forma también pero igual problema, el valor de mi cuadro de texto no se actualiza. – viky

+0

He actualizado mi pregunta, ¿me puede sugerir algo? disculpa por el retraso – viky

0

Anurag,

Hay muchas suposiciones que tengo que hacer aquí, pero voy a darle un tiro.

Es probable que tenga algo como esto ...

// ... 
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); 

} 

Esto definitivamente no es el mejor enfoque para validar los datos. Hay otros enfoques más eficientes que le darán más flexibilidad.

  1. Aplicar una ValidationRule en su TexBox.Esta es mi primera recomendación porque le dará control al mostrar el error cuando la validación falla. Si buscas una simple validación, echa un vistazo a mi article.
  2. Escuche el evento TextBox.TextChanged. Esto es engorroso y no es reutilizable en la mayoría de los pirateados.
  3. No utilice el método de devolución de llamada DependecyPropertyChanged. Use una propiedad de cadena registrada y en su setter, aplique la lógica, p.

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

Una vez más, como se puede ver en mi respuesta que todavía se puede mostrar el código en tu pregunta para ayudar a otros a responder a su pregunta, no importa lo complejo que puede ser su solución (si quieres una buena respuesta , debes esforzarte para hacer una buena pregunta). Mi respuesta puede no funcionar para usted, pero tal vez podría darle algunas instrucciones para "buscar en Google". Espero eso ayude.

+0

hev actualizó mi pregunta, perdón por el retraso ¿por qué está sucediendo con mi cuadro de texto? – viky

+0

La validación agregada al colocador en su ejemplo no ocurrirá cuando WPF actualice la propiedad a través de un enlace o un colocador o mediante otros mecanismos similares. Se recomienda nunca poner nada en sus accesadores o mutadores al usar propiedades de dependencia. – jpierson

1

Sé que esta pregunta era acerca de cuadro de texto pero para RichTextBox que usaría UpdateLayout().

rtb.AppendText("Text"); 
rtb.ScrollToEnd(); 
rtb.UpdateLayout(); 
Cuestiones relacionadas