2011-04-29 14 views
5

Estoy tratando de aprender a usar el enlace WPF y la arquitectura MVVM. Me estoy metiendo en problemas con Dependency Properties. Intenté controlar la visibilidad de un elemento en la vista vinculándolo a DependencyProperty en DataContext, pero no funciona. No importa a qué establezca el valor GridVisible en el constructor del modelo de vista a continuación, siempre se muestra como visible cuando ejecuto el código.WPF Arquitectura de enlace de datos Pregunta

¿Alguien puede ver dónde me está yendo mal?

código C# (ViewModel):

public class MyViewModel : DependencyObject 
{ 
    public MyViewModel() 
    { 
     GridVisible = false; 
    } 

    public static readonly DependencyProperty GridVisibleProperty = 
    DependencyProperty.Register(
     "GridVisible", 
     typeof(bool), 
     typeof(MyViewModel), 
     new PropertyMetadata(false, 
       new PropertyChangedCallback(GridVisibleChangedCallback))); 

    public bool GridVisible 
    { 
     get { return (bool)GetValue(GridVisibleProperty); } 
     set { SetValue(GridVisibleProperty, value); } 
    } 

    protected static void GridVisibleChangedCallback(
     DependencyObject source, 
     DependencyPropertyChangedEventArgs e) 
    { 
     // Do other stuff in response to the data change. 
    } 
} 

código XAML (Ver):

<UserControl ... > 

    <UserControl.Resources> 
     <BooleanToVisibilityConverter x:Key="BoolToVisConverter" /> 
    </UserControl.Resources> 

    <UserControl.DataContext> 
     <local:MyViewModel x:Name="myViewModel" /> 
    </UserControl.DataContext> 

    <Grid x:Name="_myGrid" 
     Visibility="{Binding Path=GridVisible, 
      ElementName=myViewModel, 
      Converter={StaticResource BoolToVisConverter}}"> 

     <!-- Other elements in here --> 

    </Grid> 

</UserControl> 

He mirado en varios tutoriales en línea, y parece como si estuviera siguiendo correctamente lo que he encontrado allí. ¿Algunas ideas? ¡Gracias!

Respuesta

2

Quite ElementName de su encuadernación, eso no parece correcto. Cambiar a:

<Grid x:Name="_myGrid" 
     Visibility="{Binding Path=GridVisible, 
      Converter={StaticResource BoolToVisConverter}}"> 
+0

Realmente copié el código y encontré que funcionaba con el enlace con y sin ElementName incluido. ¿Con qué estás usando el control de usuario (es decir, una ventana u otro control de usuario)? Quizás hay algo mal allí (código que no incluiste). – thornhill

+0

Eliminé ElementName y todavía no funciona. Aunque parece que tienes razón, probablemente tenga algo que ver con otra parte de mi código, y no con la versión esterilizada publicada anteriormente. Desafortunadamente no puedo publicar el código real ya que es por trabajo. – RobotNerd

+0

En ese caso, cuando ejecuta su aplicación y tiene la ventana abierta que contiene este control de usuario, busque en su ventana de resultados en VisualStudio cualquier error con texto similar a este "Error de ruta de BindingExpression: propiedad 'GridVisible' no encontrada en 'object ......' el contenido de ese mensaje puede ayudarlo a depurarlo aún más. lo siento, no puedo ayudarte más. buena suerte. – thornhill

0

El punto de ajuste del modelo de vista como DataContext es permitir que las consolidaciones relativas fáciles, todos los enlaces en los que sólo especificar el Path tomar la DataContext como fuente que se hereda en todo el control de usuario (a menos que sea establecer lo contrario, por ejemplo en los elementos con plantilla de un ItemsControl)

Una vez que el DataContext se configura en el UserControl, normalmente no se especifica ninguna fuente cuando se vincula a la VM. (Las fuentes son ElementName, RelativeSource y Source)

Además personalmente no hacer ViewModels heredan de DependencyObject ya que esto introduce hilo de afinidad, también el punto de DependencyProperties está haciendo estructuras de datos dispersos más eficiente al no crear campos innecesarios en todos ellos (ViewModels normalmente son todo lo contrario de escasos).

+3

'INotifyPropertyChanged' es la alternativa a' DependencyObject'; la mayoría de los viewmodels usan esto en lugar de las propiedades de dependencia. –

1

Haga que su ViewModel implemente INotifyPropertyChanged en lugar de heredar desde DependencyObject. Implementa la interfaz y levanta PropertyChanged de tu setter para la propiedad.

private bool gridVisible; 

    public bool GridVisible 
    { 
     get { return gridVisible; } 
     set 
     { 
      gridVisible = value; 
      OnPropertyChanged("GridVisible"); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected void OnPropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
+1

No necesita hacer referencia a su VM en su XAML con ElementName, ni necesita nombrar su VM. Cuando lo asigna a usercontrol.DataContext, se convierte en el origen de enlace predeterminado para todos los elementos secundarios del control de usuario. –

Cuestiones relacionadas