2009-05-05 10 views
8

Necesito averiguar cómo comunicarme entre ViewModels. Soy nuevo en MVVM así que sea amable.Patrón de MVVM, pregunta de ViewModel DataContext

Aquí hay una callados ejemplo

definiciones de clases (se supone que he enganchado caso Child.PropertyChanged en el ParentViewModel):

public class ParentViewModel : ViewModelBase 
{ 
    public ChildViewModel Child { get; set; } 
} 

public class ChildViewModel : ViewModelBase 
{ 
    String _FirstName; 
    public String FirstName 
    { 
     get { return _FirstName; } 
     set 
     { 
      _FirstName = value; 
      OnPropertyChanged("FirstName"); 
     } 
    } 
} 

Esto es lo que se ve en el diccionario de recursos

<DataTemplate DataType="{x:Type vm:ParentViewModel}"> 
    <vw:ParentView/> 
</DataTemplate> 

<DataTemplate DataType="{x:Type vm:ChildViewModel}"> 
    <vw:ChildView/> 
</DataTemplate> 

y el código detrás de ChildView:

public partial class ChildView : UserControl 
{ 
    public QueueView() 
    { 
     InitializeComponent(); 
     DataContext = new ChildViewModel(); 
    } 
} 

El problema obvio es que cuando se crea una instancia de ChildView (a través de la selección de DataTemplate) crea una nueva clase ChildViewModel y ParentViewModel no tiene acceso a ella.

Entonces, ¿cómo puedo crear una instancia del DataContext de la Vista para que sea el ViewModel original que provocó que se seleccionara DataTemplate?

Una solución obvia es fusionar las propiedades en el modelo de ChildView en el modelo de ParentView, pero prefiero separarlo para su reutilización.

Estoy seguro de que la respuesta es trivial, solo me gustaría saber de qué se trata. :)

Gracias de antemano.

+0

Por cierto, supongo que cambiaste los nombres de tus clases para simplificar el ejemplo ... El nombre de clase para "ChildView" en el código detrás es "QueueView" en su lugar. –

+0

¿Fue esto un error tipográfico? –

+0

Sí, esto era un error tipográfico. lo siento :) – Jose

Respuesta

8

Usted simplemente debe quitar la línea:

DataContext = new ChildViewModel(); 

El DataContext de la vista se establecerá automáticamente por WPF. DataTemplates siempre han su contexto conjunto de datos para los datos de la plantilla (en este caso el modelo de vista):

<DataTemplate DataType="{x:Type vm:ChildViewModel}"> 
    <vw:ChildView/> 
</DataTemplate> 

El resultado final es que usted puede construir su modelo de objetos de vista por separado (las dos clases principales y secundarios) y luego muéstrelos más tarde simplemente con conectarlos a controles de contenido.

+0

Si la intención es que un ParentView contenga un ChildView, ¿cómo se configura esto solo el DataContext de ChildView para que sea ParentViewModel.Child? –

+0

Bueno, el escenario probablemente se vería así: En una fábrica o en un método de compilación, crearía el objeto primario y secundario. Este objeto se entregará a una vista. –

+0

La vista mostraría el elemento primario en un control de contenido y el elemento secundario en otro, o mostraría ambos elementos principales y secundarios en un control de contenido con encabezado. –

1

Digamos que tiene una QueueView que utiliza un QueueViewModel.

public class QueueViewModel : INotifyPropertyChanged 
{ 
    public ParentType Parent { get; set; } 

    public QueueViewModel(ParentType parent) 
    { 
     this.Parent = parent; 
     foreach (ChildType child in Parent) 
     { 
      child.PropertyChanged += delegate(object sender, 
       PropertyChangedEventArgs e) 
      { 
       if (e.PropertyName != "IsSelected") 
        return; 

       //do something like this: 
       Parent.IsSelected = AllChildrenAreSelected(); 
      }; 
     } 
    } 

} 

public class ParentType : INotifyPropertyChanged 
{ 
    private bool _isSelected; 

    public IList<ChildType> Children { get; set; } 
    public bool IsSelected 
    { 
     get { return _isSelected; } 
     set 
     { 
      _isSelected = value; 
      OnPropertyChanged("IsSelected"); 
     } 
    } 
} 

public class ChildType : INotifyPropertyChanged 
{ 
    private string _name; 
    private bool _isSelected; 

    public string Name 
    { 
     get { return _name; } 
     set 
     { 
      _name = value; 
      OnPropertyChanged("Name"); 
     } 
    } 

    public bool IsSelected 
    { 
     get { return _isSelected; } 
     set 
     { 
      _isSelected = value; 
      OnPropertyChanged("IsSelected"); 
     } 
    } 
} 

- QueueView parte

<StackPanel> 
<CheckBlock Text="{Binding Path=Parent.Name}" 
      IsChecked="{Binding Parent.IsSelected}"/> 
<ItemsControl ItemsSource="{Binding Path=Parent.Children}"> 
    <ItemsControl.ItemTemplate> 
     <DataTemplate>          
      <CheckBox Content="{Binding Path=Name}" 
         IsChecked="{Binding Path=IsSelected, Mode=TwoWay}"/> 
     </DataTemplate> 
    <ItemsControl.ItemTemplate> 
</ItemsControl> 
</StackPanel> 
+0

Sus ejemplos de código realmente no parecen estar relacionados con la pregunta. ¿Uno o ambos nos perdemos el punto? –

+0

Estaba asumiendo que el Modelo hijo era una propiedad del Modelo principal. (por ejemplo, Pedido + Lista de detalles del pedido). En ese caso, puede usar las notificaciones de cambio de propiedad para comunicarse dentro del modelo de vista. Pero si son modelos de vista separados, puede usar el Patrón de Mediador para comunicarse. –

Cuestiones relacionadas