MVVM - Prism: Button with commands:Click inside a DataTemplate

Answered MVVM - Prism: Button with commands:Click inside a DataTemplate

  • Wednesday, October 07, 2009 5:49 PM
     
     
    Hello. I'm exploring Prism and MVVM and I've run into a little problem:

    I have a DataTemplate that is bound to a List of strings in the ViewModel and this just shows the strings inside a StackPanel (easy stuff and it works... As I said, I'm just exploring here...). I want to have a button that fires a command and I don't want to have an event handler in the code behind of the XAML. Remember, this is MVVM so no (or at least very little) code behind! But when using the Prism way of binding a command, it doesn't trigger anything.

    The thing is that if I put my button outside of the DataTemplate it triggers the command in the ViewModel, but not when it's inside the DataTemplate.

    It seems like it doesn't really know of my command in the ViewModel while inside the DataTemplate. (Just a wild guess).

    Any ideas?

    //J

All Replies

  • Wednesday, October 07, 2009 5:57 PM
     
     
    Just after I posted this I started to realise that the DataTemplate itself is really bound to my List of, well not strings as I wrote earlier, but to an object wich contains a string. This list is passed to the view by the ViewModel.

    I tried to add an handler inside this object instead, and sure enough, it fired.

    But I don't want to have eventhandler for those objects, I want to have them all in my ViewModel for the View...

    Just an update.

    //J

  • Wednesday, October 07, 2009 10:22 PM
     
     
    Hello,

    I don't know how you are binding the data template with the list. if you are setting the list as data context for the data template so when you put your button into the data template, the button is not able to "view" the command because in the data template the data context is the list. The reason why the button works fine out of the data template is because here the data context is the view model.


    Good Luck.

  • Thursday, October 08, 2009 6:35 AM
     
      Has Code

    Thank you for your reply!

    You describe my situation correctly. I suspected that the button wasn't able to "see" the ViewModel but instead looked inside the object it is bound to (that's why it triggered when I put an event handler inside my object wich the ViewModel passed to the view). But I want all my event handlers to be inside my ViewModel. This is how my xaml markup looks like:

     <UserControl.Resources>
        <DataTemplate x:Key="itemsTemplate">
                <StackPanel>
                    <TextBlock Text="{Binding Name}" Foreground="White" />
                    <Button command:Click.Command="{Binding SelectCommand}"
                                command:Click.CommandParameter="Testing" />
                </StackPanel>
        </DataTemplate>
    </UserControl.Resources>
    
    
    <Grid HorizontalAlignment="Stretch">
        <ItemsControl ItemsSource="{Binding Servers}"
                      ItemTemplate="{StaticResource itemsTemplate}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <WrapPanel Orientation="Horizontal"></WrapPanel>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ItemsControl>
    </Grid>
    The "Servers" is an ObservableCollection<Server> Servers inside the ViewModel.

    As I said, I want my button Click.Command to fire the SelectCommand inside my ViewModel and not inside my Server-object. I've been looking at RelativeSource and things like that, but my trial and error-session yesterday didn't work (I've never really used WPF this much before).

    More ideas?

    //J
  • Thursday, October 08, 2009 3:18 PM
     
     Answered
    Hello,

    Your problem is a very common situation in MVVM.
    You can execute the Select command from the button using one of the following approaches:

    Use relative source (as you propose):

    <Button command:Click.Command="{Binding DataContext.SelectCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" ...

    Or set a name to your user control and use ElementName in the binding:

    <UserControl x:Name = "MyUserControl"...>

    ...
    ...

    <Button command:Click.Command="{Binding DataContext.SelectCommand, ElementName=MyUserControl}" ...


    Good Luck!
    • Marked As Answer by jenspett Friday, October 09, 2009 7:56 AM
    •  
  • Friday, October 09, 2009 7:55 AM
     
     

    Hello HomeroThompson.

    The following markup worked PERFECTLY and was much cleaner than the other one, imo:

    <UserControl x:Name = "MyUserControl"...>

    ...
    ...

    <Button command:Click.Command="{Binding DataContext.SelectCommand, ElementName=MyUserControl}" ...

    Thank you VERY much and have a nice weekend!

    //J

  • Friday, April 13, 2012 4:58 AM
     
     

    what if the DataTemplate is inside ResourceDictionary?