Your Privacy Matters: We use our own and third-party cookies to improve your experience on our website. By continuing to use the website we understand that you accept their use. Cookie Policy
875
Problem with binding ButtonTools in application menu MenuTools
posted

My ribbon's application menu has several MenuTools in it. I was previously manually populating all those MenuItems with ButtonTools using procedural code, and was seeing proper results. The menus and buttons all looked good, like in Example 1 in my attached image.

I needed to switch to a binding approach to simplify all the internal wiring, so I converted to pure XAML for adding and populating these MenuTools in my application menu. I used an ImageSource to bind the MenuTool items to collections in my ViewModel, and used a DataTemplate specifying a ButtonTool for the MenuTool items.

Unfortunately the results aren't the same in the bound approach. The entire button content lives only in the very center of the MenuTool item. It's not using the LargeImage, and you have to click on that central button content to actually press the button. Ick.

Here's some XAML that manually adds a ButtonTool to a MenuTool, which gives the nice results like you see in Example 1 in my attached image:

<igRibbon:MenuTool Id="MyAccountMenu" Caption="My Account"
 LargeImage="/images/MyAccount_32.png">
   <igRibbon:ButtonTool Id="ChangeXperiencePasswordButton"
     Caption="Change Xperience Password" SmallImage="/images/Key_16.png"
    
LargeImage="/images/Key_32.png" Click="ChangeXperiencePasswordButton_Click" />
</igRibbon:MenuTool>

Here's some XAML that shows the binding approach. This gives the icky results like you see in Example 2 in my attached image:

<igRibbon:MenuTool Id="SelectThemeMenu" Caption="Select Theme"
 
LargeImage="/images/ThemePalette_32.png" UseLargeImages="True"
 
ItemsSource="{Binding Themes}">
   
<igRibbon:MenuTool.ItemTemplate>
       
<DataTemplate>
           
<igRibbon:ButtonTool Caption="{Binding Path=Name}"
             
SmallImage="/images/ThemePalette_16.png"
              
LargeImage="/images/ThemePalette_32.png"
             
Tag="{Binding}" Click="SelectThemeButton_Click" />
       
</DataTemplate>
   
</igRibbon:MenuTool.ItemTemplate>
</igRibbon:MenuTool>

I'm not sure why manually adding a ButtonTool as the child of a MenuTool works, while specifying a ButtonTool as the DataTemplate for a MenuTool doesn't.

I feel like I must be missing something simple here. Please tell me I don't have to fall back on procedural code to make this work! :)

Thanks for your help,
Jim Honeycutt

Parents
  • 54937
    Verified Answer
    Offline posted

    The approach that you are using will not work. Essentially the way that the menutool works is that it creates a ToolMenuItem for each item. The toolmenuitem is then initialized based on the item. If that item is a tool like a button then its content is bound to that of the menu item. In your case however, the item is some arbitrary object. So the Header of the menuitem is set to that item. The contentpresenter bound to that property then uses the itemtemplate to create some elements that it will host - a button tool in this case. So that button tool has no direct association with the toolmenuitem and therefore is just shown as a button within the menu item. What you probably want to do is to provide an ItemContainerStyle for ToolMenuItem that provides the image and uses a command (rather than hooking an event) and then just use the ItemTemplate to provide the actual content for the menu item - e.g. a textblock that binds to the Name. e.g.

        <igRibbon:XamRibbon.Resources>
            <DataTemplate DataType="{x:Type BitmapImage}">
                <Image Source="{Binding}" />
            </DataTemplate>

     

        <igRibbon:MenuTool Caption="MenuTool 2" ItemsSource="{StaticResource fooData}">
            <igRibbon:MenuTool.ItemContainerStyle>
                <Style TargetType="{x:Type igRibbon:ToolMenuItem}">
                    <Setter Property="Icon">
                        <Setter.Value>
                            <BitmapImage UriSource="\Resources\Images\Img16.bmp" />
                        </Setter.Value>
                    </Setter>
                    <!-- NotACommand is just a placeholder. You would use your command instead. -->
                    <Setter Property="Command" Value="ApplicationCommands.NotACommand" />
                    <Style.Triggers>
                        <Trigger Property="UseLargeImage" Value="True">
                            <Setter Property="Icon">
                                <Setter.Value>
                                    <BitmapImage UriSource="\Resources\Images\Img32.bmp" />
                                </Setter.Value>
                            </Setter>
                        </Trigger>
                    </Style.Triggers>
                </Style>
            </igRibbon:MenuTool.ItemContainerStyle>
            <igRibbon:MenuTool.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Name}" />
                </DataTemplate>
            </igRibbon:MenuTool.ItemTemplate>
        </igRibbon:MenuTool>

     

  • 10
    Suggested Answer
    posted in reply to Andrew Smith [Infragistics]

    Hi Andrew

    I have the same problem, but I have to set the Icon property dynamically. The ItemsSource is a list of CommandViewModels (see http://msdn.microsoft.com/en-us/magazine/dd419663.aspx). Especially for the ribbon i wrote a RibbonCommandViewModel class:

        public class RibbonCommandViewModel : CommandViewModel
        {
            #region ctor

           public RibbonCommandViewModel(string displayName, ICommand command, string largeImage, string smallImage)
                : this(displayName, command)
            {
                this.SmallImage = smallImage;
                this.LargeImage = largeImage;
            }

            #endregion

            #region Properties

            string largeImage;
            public string LargeImage
            {
                get { return largeImage; }
                set
                {
                    if (string.Equals(largeImage, value)) return;
                    largeImage = value;
                    OnPropertyChanged("LargeImage");
                }
            }

            string smallImage;
            public string SmallImage
            {
                get { return smallImage; }
                set
                {
                    if (string.Equals(smallImage, value)) return;
                    smallImage = value;
                    OnPropertyChanged("SmallImage");
                }
            }

            #endregion
        }

    Now I setting a databinding on the UriSource property.

    <BitmapImage UriSource="{Binding LargeImage}"/>

    When run, the application fails with an error, "Property 'UriSource' or property 'StreamSource' must be set.

    Can you help me?

    Robert

     

Reply Children
No Data