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
245
Application crash when adding MenuTool to the QAT
posted

Hi

Here is the case. When I try to add to QAT item that is of MenuTool type, application crash (exception is caused by trying to set in cloned control ItemsSource property to the ItemsSource collection of the original MenuTool, but cloned MenuTool already contains some items). From what I've investigated, this occurs only when MenuTool is declared  as a separate control with some ButtonTools inside, and put as an single control to the ApplicationMenu (see SeparatedMenu class in provided sample). Case doesn't happen when this kind of menu is declared as a  whole in the ApplicationMenu.

Declaring menu items as separate controls is important case for me, because ApplicationMenu is dynamically composed in runtime.

So, what are my options for being able to add such items to the QAT?

I've attached simple application that reproduces this issue.

 

QATTtest.zip
Parents
No Data
Reply
  • 54937
    Verified Answer
    Offline posted

    Unfortunately this really can't work the way you have it. I'll try to explain the process of cloning for the QAT and that might help to understand the limitations/implications. When you choose to add an element to the qat, we have to clone an instance of the tool. During the cloning of that tool we create a new instance of the source type and then copy over the properties of that type. In the case of some properties we actually bind the property on the clone to the property of the source so that the cloned tools stay in sync. Tools can get involved in the cloning process via the RibbonToolProxy. The menu tool needs to show the same items that are in the source tool since you could manipulate the source collection, make changes to the tools in that source tool, etc. The way it acheives this is by binding the ItemsSource of the clone to the Items of the source since the items for a menu will only ever be shown for 1 tool at a time.

    Well in your case when the new instance of the source type (SeparatedMenu) is created, the ctor is invoked and the way you have your tool defined means that the InitializeComponent will be executed and that cloned tool will have a new set of items in it based on the associated xaml file you have. Those tools would have no association with the tools that were in the original menu so if you changed the state of one it would not affect the tools in the cloned menu's items collection and vice versa. Worst yet is that since these are different instances they would be registered with the ribbon as new tools and if there is no id set on the tools they could be cloned again and if there is an id set, it would result in an exception because you can only have 1 instance of a tool with a given id.

    If you really want to go down this route then the only thing I could think is that you could provide a custom ribbontoolproxy that will clear the items of the cloned tool before allowing the binding of the itemssource to occur. I've attached a sample that provides 2 different options. One is to just override the Clone method and return a new MenuTool. The default binding support would bind the normal tool properties (i.e. large|smallimage, caption, isqatcommontool,visibility, isenabled, datacontext, contextmenu, tooltip, ischecked, buttontype, command, commandtarget, commandparameter). The other option is to override the Bind method and clear the items before calling the base so the itemssource can be bound to the source tool's items.

    It should be noted though that the second approach has some dangers. If you set up your xaml such that  you set an x:Name on one of those items then that element will continue to exist as the framework will store that as a member variable of the cloned instance. Also if you had tried to do element bindings based on element name then those may not work.

    QATTtest.zip
Children