Reputation: 10329
I've created a user control with two items: a button and a menu. The code below is a horribly simplified version that still has the same problems (which I will mention below).
<UserControl x:Class="gemsTouchLensApplication.Controls.ButtonAndMenu"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<StackPanel Orientation="Horizontal">
<Button/>
<Menu/>
</StackPanel>
</UserControl>
I want to be able to do two things with this usercontrol: add items to the menu and set the content of the button.
I would like to be able to add items to the menu the conventional way
<Menu>
<MenuItem Header="1"/>
<MenuItem Header="2"/>
<MenuItem Header="3"/>
<MenuItem Header="4"/>
<MenuItem Header="5"/>
etc...
</Menu>
However, when I try to do this after adding my usercontrol to a stackpanel
<Window>
<StackPanel>
<cntrls:ButtonAndMenu>
<MenuItem Header="1"/>
<MenuItem Header="2"/> <!--Comment this out and the error disappears-->
</cntrls:ButtonAndMenu>
</StackPanel>
</Window>
something unexpected happens. I can only add a single item to the usercontrol. If I add more than one item I get the error:
Property 'Content' can only be set once.
When only a single item is added the controls visual is closer to that of a button, not a menu.
I suspect that by adding controls to the usercontrol the WPF engine defaults to setting the content of the button instead of adding the controls to the menu.
How can I modify the usercontrol so that the consumer can:
Upvotes: 2
Views: 4040
Reputation: 10329
Found out how to do it.
I created a dependency property called MenuItems and bound the items source of the menu to that. I also had to set an attribute on the class of my user control.
[ContentProperty("MenuItems")]
public partial class ButtonAndMenu: UserControl
{
public ObservableCollection<DependencyObject> MenuItems
{
get { return (ObservableCollection<DependencyObject>)GetValue(MenuItemsProperty); }
set { SetValue(MenuItemsProperty, value); }
}
internal static readonly DependencyProperty MenuItemsProperty = DependencyProperty.Register(
"MenuItems", typeof(ObservableCollection<DependencyObject>), typeof(ButtonAndMenu),
new FrameworkPropertyMetadata(new ObservableCollection<DependencyObject>()));
}
and the XAML becomes:
<UserControl x:Class="gemsTouchLensApplication.Controls.ButtonAndMenu"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
x:Name="root">
<StackPanel Orientation="Horizontal">
<Button/>
<Menu ItemsSource={Binding ElementName=root, Path=MenuItems}/>
</StackPanel>
</UserControl>
Then, in a mainwindow I can do the following:
<Window>
<StackPanel>
<cntrls:ButtonAndMenu>
<MenuItem Header="1"/>
<MenuItem Header="2"/>
<MenuItem Header="3"/>
<!--etc... You can keep adding items here-->
</cntrls:ButtonAndMenu>
</StackPanel>
</Window>
So, in summary:
Upvotes: 1
Reputation: 7028
Its because MenuItem
is derived from ItemsControl
but UserControl
is a ContentControl
. You have to make ButtonAndMenu
as ItemsControl
. Why don't you make a custom MenuItemControl?
EDIT:
This link can be helpful.
1) Creating and consuming a custom WPF control. This demo shows that how you can customize a ListBox
to ColorPickerControl1
.
You can use same concept for your MenuItemControl.
You will not be using UserControl anymore and your CustomControl will look like. You need to study how to make custom controls in WPF for that.
public class MyMenuItem : MenuItem
{
// add your custom work here
}
Upvotes: 0