DisplayMemberPath when using ItemsPanelTemplate - wpf

I have a list of objects of type SomeObject that is defined like:
public struct SomeObject
{
public SomeObject(int id, string imgPath)
{
Id = id;
ImagePath = imgPath;
}
public int Id;
public string ImagePath;
}
I want to display these objects in a listbox, that shows one image for each object and arranges them in a tile layout.
The ItemsTemplate is just an Image.
The ItemsPanelTemplate is a TilePanel.
When I use just strings (image paths) as list items instead of the SombeObject items, everything works and the images are displayed correctly.
<ListBox ScrollViewer.HorizontalScrollBarVisibility="Disabled"
SelectionMode="Extended"
SelectionChanged="OnItemSelectionChanged"
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type controls:VerticalTileBox}},
Path=SomeObjectsCollectionView, UpdateSourceTrigger=PropertyChanged}"
>
<ListBox.ItemTemplate>
<DataTemplate>
<Image Source ="{Binding}"
VerticalAlignment="Center" HorizontalAlignment="Center" Stretch="Uniform" >
</Image>
</DataTemplate>
</ListBox.ItemTemplate>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<controls:VirtualizingTilePanel ChildSize="{Binding
RelativeSource={RelativeSource AncestorType={x:Type controls:VerticalTileBox}},
Path=ItemSize, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Padding" Value="0"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
When using SomeObject items, this code gives me a list of tiles but the images are not displayed.
System.Windows.Data Error: 40 : BindingExpression path error: 'ImagePath' property not found on 'object' ''SomeObject'
(HashCode=1739718653)'. BindingExpression:Path=ImagePath; DataItem='SomeObject' (HashCode=1739718653);
target element is 'Image' (Name=''); target property is 'Source' (type 'ImageSource')
This is expected, since I have not told the control, what exactly to display (which property of the SomeObject).
Using the DisplayMemberPath in addition to the ItemsPanelTemplate does not work, so how do I set the property to be used for display in the image?
Thanks for your help!
edit:
# nkoniishvt
That really sounds like the right way to do it, but I cannot get it to work properly. What am I doing wrong?
I added this DP to the UserControl code behind:
public static readonly DependencyProperty ItemsTemplateProperty =
DependencyProperty.Register("ItemsTemplate",
typeof(DataTemplate),
typeof(VerticalTileBox),
new PropertyMetadata(null));
public DataTemplate ItemsTemplate
{
get {return (DataTemplate)GetValue(ItemsTemplateProperty);}
set {SetValue(ItemsTemplateProperty, value);}
}
and changed the xaml like this:
<ListBox
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
SelectionMode="Extended"
SelectionChanged="OnItemSelectionChanged"
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type controls:VerticalTileBox}},
Path=ItemCollection, UpdateSourceTrigger=PropertyChanged}"
ItemTemplate="{Binding RelativeSource={RelativeSource AncestorType={x:Type controls:VerticalTileBox}},
Path=ItemsTemplate, UpdateSourceTrigger=PropertyChanged}"
>
<ItemsPanelTemplate>
<controls:VirtualizingTilePanel ChildSize="{Binding
RelativeSource={RelativeSource AncestorType={x:Type controls:VerticalTileBox}},
Path=ItemSize, UpdateSourceTrigger=PropertyChanged, Mode=OneWay}" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Padding" Value="0"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
The data template is defined like this:
<DataTemplate x:Name="SomeImageItemTemplate" DataType="utilities:SomeObject">
<Image Source ="{Binding Path=ImagePath}"
VerticalAlignment="Center" HorizontalAlignment="Center" Stretch="Uniform" />
</DataTemplate>
And the overall thing is used in my view like this:
<ctrls:VerticalTileBox Source="{Binding ImageListView, UpdateSourceTrigger=PropertyChanged}" ItemsTemplate="{DynamicResource SomeImageItemTemplate}"/>
The result is that the tiles are displayed but they are all empty except for the objects' class names (SomeObject).

You can't have a generic DataTemplate if the data you put as ItemsSource of your ListBox is unknown and your UserControl must remain generic.
You should let the consumer of your UserControl provide the DataTemplate instead, either in the UserControl.Resources or in a DataTemplate DP you need to create and bind to the ListBox's ItemTemplate.
Panels shouldn't say how a children is displayed, only where and how big it should be.

Related

wpf combobox not binding to collection when inside ContentTemplate

I'm trying show a certain control based on a property (combobox or textbox). So I have this contentcontrol implemented:
<!--<ComboBox MaxWidth="200" Background="#333333" ItemsSource="{Binding ModelObjectWrapper.Values}" Grid.Row="1" Grid.Column="1"/>-->
<ContentControl Grid.Row="1" Grid.Column="1">
<ContentControl.Resources>
<Style TargetType="ContentControl">
<Style.Triggers>
<DataTrigger Binding="{Binding ModelObjectWrapper.ObjType}" Value="typeA">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<ComboBox HorizontalAlignment="Left" MaxWidth="200" Background="#333333" ItemsSource="{Binding ModelObjectWrapper.Values, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
<DataTrigger Binding="{Binding ModelObjectWrapper.ObjType}" Value="typeB">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBox />
</DataTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</ContentControl.Resources>
</ContentControl>
The problem is that the combobox is not showing any items when its part of a controltemplate, and I know the bound list does have them, so I'm assuming the combobox is not being bound to the ItemsSource correctly.
The first line (having only a combobox without the templates), commented out, works fine. Am I not doing the binding right? Could it be that because its part of a datatrigger, it's not getting the right DataContext? I must note that the DataTrigger itself works great (IE showing a combobox if *.ObjType == "typeA".
The VM is a wrapper class around an object:
public class ModelObjectWrapper : ViewModelBase
{
private theModelObject model_obj;
public ModelObjectWrapper(theModelObject obj)
{
model_obj = obj;
}
public ObservableCollection<string> Values
{
get { return model_obj.Values; }
set
{
if (value == model_obj.Values)
return;
model_obj.Values = value;
OnPropertyChanged();
}
}
}
The DataContext of the root element in a ContentControl is the Content of the same ContentControl. Try to use a RelativeSource to bind to a property of the ContentControl's DataContext:
<ComboBox HorizontalAlignment="Left" MaxWidth="200" Background="#333333"
ItemsSource="{Binding DataContext.ModelObjectWrapper.Values, RelativeSource={RelativeSource AncestorType=ContentControl}}"/>
By the way, there is no point setting the UpdateSourceTrigger of an ItemsSource binding to PropertyChanged because the ComboBox never sets the source property.

How to make Catel recognise all MultiSelectTreeView properties?

I am a fairly novice Visual Basic developer trying to use the MultiSelectTreeView control (https://github.com/ygoe/MultiSelectTreeView) in a MVVM application I am developing. To become familiar with using them together, I translated the MultiSelectTreeView demo to VB, and started implementing viewmodels using Catel.
What I found is that Catel seems to make some MultiSelectTreeView properties unavailable. On running the test using Catel, the demo window opens and mostly behaves as expected, but the immediate window shows a number of errors like:
System.Windows.Data Warning: 40 : BindingExpression path error: '(Controls:MultiSelectTreeView.HoverHighlighting)' property not found on 'object' ''MultiSelectTreeView' (Name='TheTreeView')'. BindingExpression:Path=(Controls:MultiSelectTreeView.HoverHighlighting); DataItem='MultiSelectTreeView' (Name='TheTreeView'); target element is 'MultiSelectTreeViewItem' (Name=''); target property is 'HoverHighlighting' (type 'Boolean')
Similar messages are present for the MultiSelectTreeView IsKeyboardMode and ItemIndent properties. Setting these properties in code or directly in the MainWindow XAML has no effect, and the MultiSelectTreeView's HoverHighlighting effect no longer works if Catel is used.
I have uploaded my test project to GitHub (https://github.com/AnotherKiwi/MultiSelectTreeViewDemoVB). The master branch contains the VB translation of MultiSelectTreeView demo, with all features working. In the ImplementingMainWindowViewModel branch I have started implementing a viewmodel using Catel. Most features of the demo work, except the ones involving the properties mentioned above.
I would really appreciate it if someone could provide guidance on why Catel seems to be interfering with these MultiSelectTreeView properties!
Some further information added after the answer from #Geert:
The declaration of the MultiSelectTreeView control in MainWindow.xaml is as follows
<controls:MultiSelectTreeView
x:Name="TheTreeView"
ItemsSource="{Binding RootNode.Children}"
AllowEditItems="{Binding AllowEditItems}"
VerticalRulers="{Binding VerticalRulers}">
<controls:MultiSelectTreeView.ContextMenu>
...
</controls:MultiSelectTreeView.ContextMenu>
<i:Interaction.Triggers>
...
</i:Interaction.Triggers>
<controls:MultiSelectTreeView.ItemContainerStyle>
<Style TargetType="{x:Type controls:MultiSelectTreeViewItem}">
<Setter Property="DisplayName" Value="{Binding DisplayName}"/>
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/>
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
<Setter Property="IsEnabled" Value="{Binding IsEnabled, Mode=TwoWay}"/>
<Setter Property="IsVisible" Value="{Binding IsVisible, Mode=TwoWay}"/>
<Setter Property="IsEditable" Value="{Binding IsEditable, Mode=TwoWay}"/>
<Setter Property="IsEditing" Value="{Binding IsEditing, Mode=TwoWay}"/>
<Setter Property="Remarks" Value="{Binding Remarks}"/>
<Setter Property="IsKeyboardMode" Value="{Binding IsKeyboardMode, Mode=TwoWay}"/>
<Setter Property="HoverHighlighting" Value="{Binding HoverHighlighting}"/>
<Setter Property="ItemIndent" Value="{Binding ItemIndent}"/>
<Setter Property="ToolTip" Value="{Binding ToolTip}" />
<Setter Property="ContentTemplateEdit">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Border Background="YellowGreen" CornerRadius="3" Width="16" Height="16"/>
<controls:EditTextBox
Text="{Binding DisplayName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Padding="2,0,0,0"/>
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</controls:MultiSelectTreeView.ItemContainerStyle>
<controls:MultiSelectTreeView.Resources>
<!--
Here the general item appearance is defined, for the ViewModel.TreeItemViewModel type
-->
<HierarchicalDataTemplate DataType="{x:Type vm:TreeItemViewModel}" ItemsSource="{Binding DataContext.Children}">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding DataContext.ImageSource}" Width="16" Height="16" SnapsToDevicePixels="True"/>
<TextBlock Text="{Binding DataContext.DisplayName}" VerticalAlignment="Center" Padding="4,0,2,0"/>
</StackPanel>
</HierarchicalDataTemplate>
</controls:MultiSelectTreeView.Resources>
</controls:MultiSelectTreeView>
I have tried applying the advice given in #Geert's answer, but when I run the application the MultiSelectTreeView is not displayed. I'm very new to WPF and I'm probably not modifying the appropriate XAML statements. Some more help with this would be really appreciated!
Note that items in an itemscontrol get a new DataContext (which is the item), so you cannot bind directly to the VM inside an ItemTemplate.
If you need to bind to the vm, you should do something like this:
<ItemsControl x:Name="myItemsControl" ItemsSource="{Binding MyItems}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBlock Content="{Binding ElementName=myItemsControl, Path=DataContext.SomePropertyOnTheVm}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

WPF MVVM-Light adding an image to a listview item when selecting

I have a ListView that I want to be able to add a 'Delete' button to, with a command attached to it, when I select an item. I can't find anything about this on stack which is quite surprising.
One way you could do this is by applying a style to the ListViewItem in the ListView.Resources. In the Style, you set the ContentTemplate to a DataTemplate with only a TextBlock. Then you give the Style a Trigger that is tied to the IsSelected property. In the Trigger you'll set the ContentTemplate to a new DataTemplate with a TextBlock and a Button. The Command property of the Button is bound to the ViewModel using the RelativeSource binding and the CommandParameter is bound to the item so that it gets passed along as a parameter to your DeleteCommand.
XAML
<ListView Margin="3"
MinWidth="200"
ItemsSource="{Binding Items}">
<ListView.Resources>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding SomeProperty}"
Margin="3" />
</DataTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected"
Value="True">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding SomeProperty}"
Margin="3" />
<Button Content="Delete"
Margin="3"
Command="{Binding DataContext.DeleteCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListView}}}"
CommandParameter="{Binding }" />
</StackPanel>
</DataTemplate>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</ListView.Resources>
</ListView>
ViewModel
private ICommand _DeleteCommand;
public ICommand DeleteCommand
{
get
{
if (_DeleteCommand == null)
{
_DeleteCommand = new RelayCommand<ExampleModel>(param => DeleteItem(param));
}
return _DeleteCommand;
}
}
private void DeleteItem(ExampleModel item)
{
MessageBox.Show(item.SomeProperty);
}
I just have the Delete method showing the value in a MessageBox for demo purposes. You should be able to modify the DataTemplate and Delete method to meet your needs.

Windows Phone - Bind Button of UserControl to ViewModel

i am struggling with binding a Button inside of a UserControl (which is placed inside of a ListBox.ItemTemplate) to my ViewModel.
Page A contains the following Listbox:
<ListBox x:Name="lbUpcomingBetgames" ItemsSource="{Binding UpcomingBetgames}" Background="{x:Null}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Margin" Value="0,4,0,4"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<customControl:BetgameInfoControl x:Name="upcomingBetgameControl" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
My ViewModel contains a RelayCommand that i want to bind to in my CustomControl BetgameInfoControl:
public RelayCommand BetgameRegisterClicked
{
get;
private set;
}
My CustomControl contains a Button:
<Button Grid.Row="0" Content="Accept" Height="50" Command="{Binding Path=Parent.DataContext.BetgameRegisterClicked, ElementName=upcomingBetgameControl}" CommandParameter="{Binding Description}" />
The RelayCommand is never called. I tried different ways to bind the Command-Property in my Button but nothing worked.
Can someone help me please?
You need to change the datacontext of your button like this =>
DataContext={Binding ElementName=lbUpcomingBetgames,path=DataContext.BetgameRegisterClicked}

How can I bind an ObservableCollection of ViewModels to a MenuItem?

When I bind Menu Items with an ObservableCollection, only the "inner" area of the MenuItem is clickable:
alt text http://tanguay.info/web/external/mvvmMenuItems.png
In my View I have this menu:
<Menu>
<MenuItem
Header="Options" ItemsSource="{Binding ManageMenuPageItemViewModels}"
ItemTemplate="{StaticResource MainMenuTemplate}"/>
</Menu>
Then I bind it with this DataTemplate:
<DataTemplate x:Key="MainMenuTemplate">
<MenuItem
Header="{Binding Title}"
Command="{Binding DataContext.SwitchPageCommand,
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Menu}}}"
Background="Red"
CommandParameter="{Binding IdCode}"/>
</DataTemplate>
Since each ViewModel in the ObservableCollection ManageMenuPageItemViewModels has a property Title and IdCode, the above code works fine at first sight.
HOWEVER, the problem is that the MenuItem in the DataTemplate is actually inside another MenuItem (as if it is being bound twice) so that in the above DataTemplate with Background="Red" there is a Red box inside each menu item and only this area can be clicked, not the whole menu item area itself (e.g. if the user clicks on the area where the checkmark is or to the right or left of the inner clickable area, then nothing happens, which, if you don't have a separate color is very confusing.)
What is the correct way to bind MenuItems to an ObservableCollection of ViewModels so that the whole area inside each MenuItem is clickable?
UPDATE:
So I made the following changes based on advice below and now have this:
alt text http://tanguay.info/web/external/mvvmMenuItemsYellow.png
I have only a TextBlock inside my DataTemplate, but I still can't "color the whole MenuItem" but just the TextBlock:
<DataTemplate x:Key="MainMenuTemplate">
<TextBlock Text="{Binding Title}"/>
</DataTemplate>
And I put the Command binding into Menu.ItemContainerStyle but they don't fire now:
<Menu DockPanel.Dock="Top">
<Menu.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Background" Value="Yellow"/>
<Setter Property="Command" Value="{Binding DataContext.SwitchPageCommand,
RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Menu}}}"/>
<Setter Property="CommandParameter" Value="{Binding IdCode}"/>
</Style>
</Menu.ItemContainerStyle>
<MenuItem
Header="MVVM" ItemsSource="{Binding MvvmMenuPageItemViewModels}"
ItemTemplate="{StaticResource MainMenuTemplate}"/>
<MenuItem
Header="Application" ItemsSource="{Binding ApplicationMenuPageItemViewModels}"
ItemTemplate="{StaticResource MainMenuTemplate}"/>
<MenuItem
Header="Manage" ItemsSource="{Binding ManageMenuPageItemViewModels}"
ItemTemplate="{StaticResource MainMenuTemplate}"/>
</Menu>
I found using MVVM with MenuItems to be very challenging. The rest of my application uses DataTemplates to pair the View with the ViewModel, but that just doesn't seem to work with Menus because of exactly the reasons you've described. Here's how I eventually solved it. My View looks like this:
<DockPanel>
<Menu DockPanel.Dock="Top" ItemsSource="{Binding Path=(local:MainViewModel.MainMenu)}">
<Menu.ItemContainerStyle>
<Style>
<Setter Property="MenuItem.Header" Value="{Binding Path=(contracts:IMenuItem.Header)}"/>
<Setter Property="MenuItem.ItemsSource" Value="{Binding Path=(contracts:IMenuItem.Items)}"/>
<Setter Property="MenuItem.Icon" Value="{Binding Path=(contracts:IMenuItem.Icon)}"/>
<Setter Property="MenuItem.IsCheckable" Value="{Binding Path=(contracts:IMenuItem.IsCheckable)}"/>
<Setter Property="MenuItem.IsChecked" Value="{Binding Path=(contracts:IMenuItem.IsChecked)}"/>
<Setter Property="MenuItem.Command" Value="{Binding}"/>
<Setter Property="MenuItem.Visibility" Value="{Binding Path=(contracts:IMenuItem.Visible),
Converter={StaticResource BooleanToVisibilityConverter}}"/>
<Setter Property="MenuItem.ToolTip" Value="{Binding Path=(contracts:IMenuItem.ToolTip)}"/>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=(contracts:IMenuItem.IsSeparator)}" Value="true">
<Setter Property="MenuItem.Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MenuItem}">
<Separator Style="{DynamicResource {x:Static MenuItem.SeparatorStyleKey}}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Menu.ItemContainerStyle>
</Menu>
</DockPanel>
If you notice, I defined an interface called IMenuItem, which is the ViewModel for a MenuItem. Here's the code for that:
public interface IMenuItem : ICommand
{
string Header { get; }
IEnumerable<IMenuItem> Items { get; }
object Icon { get; }
bool IsCheckable { get; }
bool IsChecked { get; set; }
bool Visible { get; }
bool IsSeparator { get; }
string ToolTip { get; }
}
Notice that the IMenuItem defines IEnumerable Items, which is how you get sub-menus. Also, the IsSeparator is a way to define separators in the menu (another tough little trick). You can see in the xaml how it uses a DataTrigger to change the style to the existing separator style if IsSeparator is true. Here's how MainViewModel defines the MainMenu property (that the view binds to):
public IEnumerable<IMenuItem> MainMenu { get; set; }
This seems to work well. I assume you could use an ObservableCollection for the MainMenu. I'm actually using MEF to compose the menu out of parts, but after that the items themselves are static (even though the properties of each menu item are not). I also use an AbstractMenuItem class that implements IMenuItem and is a helper class to instantiate menu items in the various parts.
UPDATE:
Regarding your color problem, does this thread help?
Don't put the MenuItem in the DataTemplate. The DataTemplate defines the content of the MenuItem. Instead, specify extraneous properties for the MenuItem via the ItemContainerStyle:
<Menu>
<Menu.ItemContainerStyle>
<Style TargetType="MenuItem">
<Setter Property="Header" Value="{Binding Title}"/>
...
</Style>
</Menu.ItemContainerStyle>
<MenuItem
Header="Options" ItemsSource="{Binding ManageMenuPageItemViewModels}"
ItemTemplate="{StaticResource MainMenuTemplate}"/>
</Menu>
Also, take a look at HierarchicalDataTemplates.
Here is how I have done my menus. It may not be precisely what you need, but I think it is pretty close.
<Style x:Key="SubmenuItemStyle" TargetType="MenuItem">
<Setter Property="Header" Value="{Binding MenuName}"></Setter>
<Setter Property="Command" Value="{Binding Path=MenuCommand}"/>
<Setter Property="ItemsSource" Value="{Binding SubmenuItems}"></Setter>
</Style>
<DataTemplate DataType="{x:Type systemVM:TopMenuViewModel}" >
<Menu>
<MenuItem Header="{Binding MenuName}"
ItemsSource="{Binding SubmenuItems}"
ItemContainerStyle="{DynamicResource SubmenuItemStyle}" />
</Menu>
</DataTemplate>
<Menu DockPanel.Dock="Top" ItemsSource="{Binding Menus}" />
TopMenuViewModel is a collection of the menus that will appear on the menu bar. They each contain the MenuName that will be displayed and a collection called SubMenuItems that I set to be the ItemsSource.
I control the way the SubMenuItems are displayed by way of the style SumMenuItemStyle. Each SubMenuItem has its own MenuName property, Command property of type ICommand, and possibly another collection of SubMenuItems.
The result is that I am able to store all my menu information in a database and dynamically switch what menus are displayed at runtime. The entire menuitem area is clickable and displays correctly.
Hope this helps.
Just make your DataTemplate to be a TextBlock (or maybe a stack panel with an icon and a TextBlock).

Resources