Populating Ribbon QuickAccessToolBar with Buttons from ViewModel

Topics: Prism v2 - WPF 3.5
Mar 9, 2010 at 2:06 PM

Hi

I am trying to bind my QuickAccessToolbar to ObservableCollection in my ViewModel Class. Basically I want to have as much buttons in quickaccesstoolbar as there is in observablecollection plus i want all of them to be able to invoke a PromijeniStranicuCommand.

I am able to get the buttons drawn but they dont invoke the command. What am I doing wrong?

Thanks in advance!

XAML:

xmlns:cal="http://www.codeplex.com/CompositeWPF"

xmlns:cmd="clr-namespace:Microsoft.Practices.Composite.Presentation.Commands;assembly=Microsoft.Practices.Composite.Presentation"

xmlns:r="clr-namespace:Microsoft.Windows.Controls.Ribbon;assembly=RibbonControlsLibrary"

 

  <r:Ribbon.QuickAccessToolBar  >
                <r:RibbonQuickAccessToolBar ItemsSource="{Binding RibbonButtonList}">
                    <r:RibbonQuickAccessToolBar.ItemTemplate>
                                              
                        <DataTemplate>
                                                                             
                         <r:RibbonButton Margin="5"  
                                         cmd:Click.Command="{Binding PromijeniStranicuCommand}" /> 
                        </DataTemplate>
                        
                    </r:RibbonQuickAccessToolBar.ItemTemplate>
                    <!--  cmd:Click.Command="{Binding PromijeniStranicuCommand}"-->
                    <!--<ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <r:RibbonButton Content="{Binding}" Margin="5"
                                cmd:Click.Command="{Binding PromijeniStranicuCommand, ElementName=stack}"
                                cmd:Click.CommandParameter="{Binding}"/>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>-->
                    <!--<r:RibbonButton cmd:Click.Command="{Binding PromijeniStranicuCommand}" 
                                    cmd:Click.CommandParameter="0" 
                                    Foreground="Black"/>
                    <r:RibbonButton cmd:Click.Command="{Binding PromijeniStranicuCommand}"   cmd:Click.CommandParameter="1"/>
                    <r:RibbonButton cmd:Click.Command="{Binding HomeCommand}"/>-->
                    <!--<ItemsControl  x:Name="toolbox" ItemsSource="{Binding RibbonButtonList}">
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <r:RibbonButton Content="{Binding}" Margin="5"
                                cmd:Click.Command="{Binding PromijeniStranicuCommand, ElementName=stack}"
                                cmd:Click.CommandParameter="{Binding}"/>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                    </ItemsControl>-->
                </r:RibbonQuickAccessToolBar>
            </r:Ribbon.QuickAccessToolBar>

  <r:Ribbon.QuickAccessToolBar  >

                <r:RibbonQuickAccessToolBar ItemsSource="{Binding RibbonButtonList}">

                    <r:RibbonQuickAccessToolBar.ItemTemplate>

                         <DataTemplate>

                             <r:RibbonButton Margin="5"  

                                         cmd:Click.Command="{Binding PromijeniStranicuCommand}" /> 

                        </DataTemplate>

                   </r:RibbonQuickAccessToolBar>

    </r:Ribbon.QuickAccessToolBar>

VIEWMODEL:

 Public Sub New(ByVal view As IMainToolbar, ByVal eventAggregator As IEventAggregator,  ByVal regionManager As IRegionManager)

        Me.View = view

        Me.View.Model = Me

        Me.eventAggregator = eventAggregator

        Me._regionmanager = regionManager

        Me.PromijeniStranicuCommand = New DelegateCommand(Of String)(AddressOf OnPromijeniStranicuCommand)

 End Sub

 Private Sub OnPromijeniStranicuCommand(ByVal arg As String)

          'Something

 End Sub

 Private lRibbonButtonList As ObservableCollection(Of RibbonButton)

  Public Property RibbonButtonList() As ObservableCollection(Of RibbonButton)

        Get

            Return Me.lRibbonButtonList

        End Get

        Set(ByVal value As ObservableCollection(Of RibbonButton))

            If Me.lRibbonButtonList IsNot value Then

                Me.lRibbonButtonList = value

                OnPropertyChanged("RadRibbonButtonList")

            End If

        End Set

 End Property

 

 

Developer
Mar 12, 2010 at 1:54 PM

The commands are probably not being invoked because when you use Binding without a source, you are implicitly saying that the source is the DataContext; and inside the DataTemplate, the DataContext is no longer your ViewModel, but rather the ItemsSource you specified. So the application is trying to find the PromijeniStranicuCommand inside the RibbonButtonList.

A possible workaround would be to substitute bindings like this:

cmd:Click.Command="{Binding PromijeniStranicuCommand}"

using RelativeSource bindings, like this:

cmd:Click.Command="{Binding DataContext.PromijeniStranicuCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"

Assuming there is a public property in the ViewModel that holds the PromijeniStranicuCommand.

This approach has also been taken in the WPF Reference Implementation, in the WatchListView.xaml file inside the StockTraderRI.Modules.Watch project. A similar problem is explained in this thread.

I hope you find this answer helpful.

Guido Leandro Maliandi
http://blogs.southworks.net/gmaliandi