Home > Software design >  WPF Insert multiple elements to custom control
WPF Insert multiple elements to custom control

Time:10-26

I have my custom control:

MenuButtonControl.xaml

<UserControl
 (...)
    >
    <Grid>
        <ItemsControl
            x:Name="tStack"
            ItemsSource="{Binding MenuItems}"
            Visibility="{Binding IsChecked, ElementName=toggleButton, Converter={StaticResource BoolToVisibilityConverter}}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Horizontal" />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <ContentPresenter Content="{Binding}" />
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

        <ToggleButton x:Name="toggleButton" Content="Toggle" />
    </Grid>
</UserControl>

MenuButtonControl.xaml.cs

public partial class MenuButtonControl : UserControl
{
    public MenuButtonControl()
    {
        InitializeComponent();
        DataContext = this;
    }

    public static readonly DependencyProperty MenuItemsProperty =
        DependencyProperty.Register("ItemTemplate", typeof(ICollection<UIElement>), typeof(MenuButtonControl), new UIPropertyMetadata(null));
    public ICollection<UIElement> MenuItems
    {
        get { return (ICollection<UIElement>)GetValue(MenuItemsProperty); }
        set { SetValue(MenuItemsProperty, value); }
    }
}

The idea is that I have a toggle button that pops up a menu when I click it. I would like to provide menu items as elements of a control collection (e.g. Buttons).

The problem is that I don't know how to configure my control to accept these items as in the example below:

<Controls:MenuButtonControl Grid.Row="1">
    <Button Content="Test 1" />
    <Button Content="Test 2" />
    <Button Content="Test 3" />
</Controls:MenuButtonControl>

CodePudding user response:

Derive from ItemsControl or decorate your control with the ContentPropertyAttribute:

[ContentProperty(nameof(MenuItems))]
public partial class MenuButtonControl : UserControl
{
    public MenuButtonControl()
    {
        InitializeComponent();
        MenuItems = new ObservableCollection<UIElement>();
    }

    public static readonly DependencyProperty MenuItemsProperty =
        DependencyProperty.Register(nameof(MenuItems), typeof(ObservableCollection<UIElement>), 
            typeof(MenuButtonControl), new UIPropertyMetadata(null));
    
    public ObservableCollection<UIElement> MenuItems
    {
        get { return (ObservableCollection<UIElement>)GetValue(MenuItemsProperty); }
        set { SetValue(MenuItemsProperty, value); }
    }
}

MenuButtonControl.xaml:

<ItemsControl
    x:Name="tStack"
    ItemsSource="{Binding MenuItems, RelativeSource={RelativeSource AncestorType=UserControl}}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Orientation="Horizontal" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <ContentPresenter Content="{Binding}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Usage:

<Controls:MenuButtonControl Grid.Row="1">
    <Button Content="Test 1" />
    <Button Content="Test 2" />
    <Button Content="Test 3" />
</Controls:MenuButtonControl>
  • Related