2010-07-22 1 views
9

La lumière MVVM a été un plaisir d'apprendre, mais je suis coincé ici. Le problème est le déclenchement d'un événement.MVVM-Light, déclencher des événements à partir d'un bouton à l'intérieur d'un modèle de colonne de la grille de données

Dans le code ci-dessous, un bouton le travail et déclenche des événements. L'autre bouton ne marche pas. Aucune erreur de liaison n'est signalée dans la sortie. Y a-t-il quelque chose d'évident qui me manque?

<Grid x:Name="LayoutRoot">... 
<StackPanel> 
    <Button Content="THIS BUTTON WORKS"> 
    <i:Interaction.Triggers> 
     <i:EventTrigger EventName="Click"> 
     <Command:EventToCommand Command="{Binding DataContext.HandleAddQuestionActionCommand, ElementName=LayoutRoot, Mode=OneWay}" PassEventArgsToCommand="True"/> 
     </i:EventTrigger> 
    </i:Interaction.Triggers> 
    </Button> 
    <sdk1:DataGrid ItemsSource="{Binding QuestionActions}" AutoGenerateColumns="False" > 
    <sdk1:DataGrid.Columns> 
     <sdk1:DataGridTextColumn Binding="{Binding Answer.Name}" Header="Answer"/> 
     <sdk1:DataGridTemplateColumn Header="Edit"> 
      <sdk1:DataGridTemplateColumn.CellTemplate> 
      <DataTemplate> 
       <Button Content="THIS BUTTON DONT WORK" > 
       <i:Interaction.Triggers> 
        <i:EventTrigger EventName="Click"> 
        <Command:EventToCommand Command="{Binding DataContext.HandleEditQuestionActionCommand, ElementName=LayoutRoot, Mode=OneWay}" PassEventArgsToCommand="True"/> 
        </i:EventTrigger> 
       </i:Interaction.Triggers> 
       </Button> 
      </DataTemplate> 
      </sdk1:DataGridTemplateColumn.CellTemplate> 
     </sdk1:DataGridTemplateColumn> 
    </sdk1:DataGrid.Columns> 
    </sdk1:DataGrid> 
</StackPanel> 

Code ViewModel:

public RelayCommand<RoutedEventArgs> HandleAddQuestionActionCommand { 
    get; private set; 
} 
public RelayCommand<RoutedEventArgs> HandleEditQuestionActionCommand { 
    get; private set; 
} 


HandleAddQuestionActionCommand = new RelayCommand<RoutedEventArgs>(e =>{...}); 
HandleEditQuestionActionCommand = new RelayCommand<RoutedEventArgs>(e =>{...}); 

Répondre

9

Votre contexte de perte de données dans le DataGrid DataGridTemplateColumn car DataGrid.Columns n'est pas une propriété de dépendance. Pour cette raison, vous ne pouvez pas utiliser la liaison de données d'élément à élément depuis votre DataGridTemplateColumn.

Cependant, ceci est facilement résolu grâce à ViewModelLocator de MVVM Light Toolkit.

Je ne sais pas ce que votre ViewModel est appelé, mais en supposant qu'il est MainViewModel vous pouvez modifier votre touche de connexion à ceci:

<sdk1:DataGridTemplateColumn Header="Edit"> 
    <sdk1:DataGridTemplateColumn.CellTemplate> 
     <DataTemplate> 
      <Button Content="THIS BUTTON WILL WORK NOW ;-)" > 
       <i:Interaction.Triggers> 
        <i:EventTrigger EventName="Click"> 
         <Command:EventToCommand Command="{Binding Source={StaticResource Locator}, 
                    Path=MainViewModel.HandleEditQuestionActionCommand}" 
               PassEventArgsToCommand="True" /> 
        </i:EventTrigger> 
       </i:Interaction.Triggers> 
      </Button> 
     </DataTemplate> 
    </sdk1:DataGridTemplateColumn.CellTemplate> 
</sdk1:DataGridTemplateColumn> 
+0

C'est exactement ce dont j'avais besoin! Merci, et avec cela, MVVM-lumière continue d'être une approche simple et élégante à Silverlight dans tous les scénarios. Merci encore – nachonachoman

+0

Est-ce que cela fonctionne aussi bien dans Silverlight ou seulement dans WPF? – Radhi

+0

Cet exemple a été créé dans Silverlight, pas WPF. –

0

Le bouton à l'intérieur du DataGrid a une DataContext de QuestActions depuis la liaison est basée sur la propriété ItemSource du DataGrid. Cela étant le cas, vous devrez trouver le DataContext du DataGrid lui-même (ou UserControl ou tout parent qui a le commandement dans son DataContext) pour accéder à votre commande:

<Command:EventToCommand 
Command="{Binding RelativeSource={RelativeSource FindAncestor, 
AncestorType={x:Type sdk1:DataGrid}}, 
Path=DataContext.ViewSchemaCommand, Mode=OneWay}" 
PassEventArgsToCommand="True" /> 
+1

-moi si je me trompe, mais ne sont pas les FindAncestor et AncestorType bidules seulement disponible en WPF? –

+0

La théorie est correcte cependant, vous avez besoin de lier au DataContext du DataGrid parent. Dans ce fil est une solution de contournement que vous pourriez vouloir regarder: http://forums.silverlight.net/forums/p/163476/367975.aspx –

+0

Vraiment? Je n'ai pas réalisé FindAncestor et AncestorType étaient WPF seulement. –

0

Cette solution ne fonctionne que pour les modèles statiques de vue. Découvrez la page de Dan Whalin pour une réponse alternative. http://weblogs.asp.net/dwahlin/archive/2009/08/20/creating-a-silverlight-datacontext-proxy-to-simplify-data-binding-in-nested-controls.aspx

Vous pouvez créer une ressource comme si (ne pas oublier votre référence):

<UserControl.Resources> 
    <controls:DataContextProxy x:Key="DataContextProxy" /> 
</UserControl.Resources> 

ou

<sdk:Page.Resources> 
    <controls:DataContextProxy x:Key="DataContextProxy"/> 
</sdk:Page.Resources> 

Utilisation dans le contrôle comme ceci:

<sdk:DataGridTemplateColumn> 
<sdk:DataGridTemplateColumn.CellTemplate> 
    <DataTemplate> 
     <Button Content="Content"> 
      <i:Interaction.Triggers> 
       <i:EventTrigger EventName="Click"> 
        <cmd:EventToCommand Command="{Binding Source={StaticResource DataContextProxy}, Path=DataSource.MyCommand}" 
             CommandParameter="{Binding Path=SomeValue}" 
             PassEventArgsToCommand="False">  
        </cmd:EventToCommand> 
       </i:EventTrigger> 
      </i:Interaction.Triggers> 
     </Button> 
    </DataTemplate> 
</sdk:DataGridTemplateColumn.CellTemplate> 

ViewModel Définir RelayCommand:

public RelayCommand<object> MyCommand { get; set; } 

Set RelayCommand dans Constructor:

MyCommand = new RelayCommand<object>((e) => 
     { 
      if (e != null && e is int) 
      { 
       int varName = int.Parse(e.ToString()); 

       //DoSomething... 
      } 
     }); 
Questions connexes