2010-07-22 10 views
9

Światło MVVM było przyjemnością do nauki, ale tutaj utknąłem. Problem polega na wystrzeliwaniu zdarzeń.MVVM-Light, wystrzeliwanie zdarzeń z przycisku wewnątrz szablonu kolumny siatki danych

W kodzie poniżej jeden przycisk uruchamia zdarzenia i pożary. Drugi przycisk nie robi. Na wyjściu nie są zgłaszane żadne błędy wiązania. Czy jest coś oczywistego, czego mi brakuje?

<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> 

kod 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 =>{...}); 

Odpowiedz

9

context dane zostaną utracone w DataGrid DataGridTemplateColumn, ponieważ DataGrid.Columns nie jest właściwością zależności. Z tego powodu nie można używać wiązania danych element-element z poziomu obiektu DataGridTemplateColumn.

Jednak można to łatwo naprawić dzięki narzędziu ViewModelLocator MVVM Light Toolkit.

Nie wiem, co się nazywa ViewModel, ale zakładając, że jest MainViewModel można zmienić przycisk wiążący do tego:

<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

Dokładnie tego potrzebowałem! Dziękuję, a wraz z tym MVVM-light nadal jest prostym i eleganckim podejściem do silverlight we wszystkich scenariuszach. Jeszcze raz dziękuję – nachonachoman

+0

Czy to działa również w silverlight lub działa tylko w WPF? – Radhi

+0

Ten przykład został utworzony w programie Silverlight, a nie w WPF. –

0

Przycisk wewnątrz DataGrid ma DataContext QuestActions Ponieważ wiązanie jest oparte na DataGrid za ItemSource Property. Skoro tak, to trzeba znaleźć DataContext samego DataGrid (lub UserControl lub cokolwiek rodzic, który ma polecenie w to DataContext), aby dostać się do polecenia:

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

Popraw mnie jeśli się mylę, ale nie są FindAncestor i thingies AncestorType dostępny tylko w WPF? –

+0

Teoria jest jednak prawidłowa, konieczne jest powiązanie z DataContext nadrzędnej DataGrid. W tym wątku jest obejście, na które możesz spojrzeć: http://forums.silverlight.net/forums/p/163476/367975.aspx –

+0

Naprawdę? Nie zdawałem sobie sprawy, że FindAncestor i AncestorType były tylko typu WPF. –

0

To rozwiązanie działa tylko dla widoku statycznych modeli. sprawdź stronę Dana Whalina, aby uzyskać alternatywną odpowiedź. http://weblogs.asp.net/dwahlin/archive/2009/08/20/creating-a-silverlight-datacontext-proxy-to-simplify-data-binding-in-nested-controls.aspx

Można utworzyć zasób jak tak (nie zapomnij odniesienia):

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

lub

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

zastosowanie w zwalczaniu tak:

<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 Definiowanie RelayCommand:

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

zestaw RelayCommand w konstruktorze:

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

       //DoSomething... 
      } 
     }); 
Powiązane problemy