Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I'll confess that I haven't dug quite as deep into your example as maybe I should, but whenever I see code-behind that's searching the visual tree, I think, could this be handled more explicitly in a view model? </p> <p>It seems to me in this case that you could come up with a pretty straightforward view model - an object exposing <code>Text</code>, <code>Image</code>, <code>Command</code>, and <code>Children</code> properties, for instance - and then create a simple data template that for presenting it as a <code>MenuItem</code>. Then anything that needs to alter the contents of your menus manipulates this model.</p> <p><strong>Edit:</strong></p> <p>Having looked at what you're up to in more detail, and the two examples you've linked to in your blog post, I am banging my head against the desk. Both of those developers appear to be under the misapprehension that the way to set properties on the menu items that are being generated by the template is to search through the visual tree in the <code>ContentPresenter.Load</code> event after they're created. Not so. That's is what the <code>ItemContainerStyle</code> is for.</p> <p>If you use that, it's quite straightforward to create dynamic menus of the type you're describing. You need a <code>MenuItemViewModel</code> class that has <code>INotifyPropertyChanged</code> implemented and exposes these public properties:</p> <pre><code>string Text Uri ImageSource ICommand Command ObservableCollection&lt;MenuItemViewModel&gt; Children </code></pre> <p>Using this:</p> <pre><code>&lt;Menu DockPanel.Dock="Top" ItemsSource="{DynamicResource Menu}"/&gt; </code></pre> <p>where the <code>ItemsSource</code> is an <code>ObservableCollection&lt;MenuItemViewModel&gt;</code>, and using this template:</p> <pre><code>&lt;HierarchicalDataTemplate DataType="{x:Type local:MenuItemViewModel}" ItemsSource="{Binding Path=Children}"&gt; &lt;HierarchicalDataTemplate.ItemContainerStyle&gt; &lt;Style TargetType="MenuItem"&gt; &lt;Setter Property="Command" Value="{Binding Command}" /&gt; &lt;/Style&gt; &lt;/HierarchicalDataTemplate.ItemContainerStyle&gt; &lt;StackPanel Orientation="Horizontal"&gt; &lt;Image Source="{Binding ImageSource}" /&gt; &lt;Label Content="{Binding Text}" /&gt; &lt;/StackPanel&gt; &lt;/HierarchicalDataTemplate&gt; </code></pre> <p>the menus in the window exactly represent what's in the collection, and are dynamically updated as items are added and removed, both to the top-level items and to the descendants.</p> <p>There's no clambering about in the visual tree, no manual creation of objects, no code-behind (other than in the view model, and in whatever populates the collection in the first place).</p> <p>I've built a pretty thoroughly worked example of this; you can download the project <a href="http://www.koaxkoaxkoax.com/stackoverflow/MenuItemDataBindingDemo.zip" rel="noreferrer">here</a>.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload