简体   繁体   中英

How to instantiate UserControl and add Items to its Container in XAML

I have the following UserControl:

<UserControl x:Class="UserControlTest.UserControl"
         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 x:Name="MainPanel" Background="White">
    <TextBlock Text="BasePanel"/>
</StackPanel>

And my MainWindwo.XAML:

<Window x:Class="UserControlTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:UC="clr-namespace:UserControlTest"
    Title="MainWindow" Height="350" Width="525">
<DockPanel Name="dpMain">
    <UC:Control x:Name="ucBaseControl" />

</DockPanel>

In the code-behind MainWindow.xaml.cs:

namespace UserControlTest
{
    /// <summary>
    /// Interaktionslogik für MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            TextBox tbWorld = new TextBox();
            tbWorld.Text = "Hello World";
            ucBaseControl.MainPanel.Children.Add(tbWorld);
        }
    }
}

Is there a way to achieve this in XAML to avoid code-behind?

Thank you very much in advance!

You could try to do something like:

XAML:

<UserControl x:Class="WpfApplication1.BaseControl"
             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 x:Name="root">
        <TextBlock>I'm from base</TextBlock>
        <StackPanel x:Name="newPanel">

        </StackPanel>
    </StackPanel>
</UserControl>

Code behind:

using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;

namespace WpfApplication1
{
    [ContentProperty("NewControls")]
    public partial class BaseControl : UserControl
    {
        public UIElementCollection NewControls
        {
            get { return (UIElementCollection)GetValue(NewControlsProperty); }
            set { SetValue(NewControlsProperty, value); }
        }

        public static readonly DependencyProperty NewControlsProperty = DependencyProperty.Register("NewControls", typeof(UIElementCollection), typeof(BaseControl));

        public BaseControl()
        {
            InitializeComponent();

            this.NewControls = new UIElementCollection(this, this);

            this.Loaded += BaseControl_Loaded;
        }

        void BaseControl_Loaded(object sender, RoutedEventArgs e)
        {
            foreach (UIElement element in NewControls.Cast<UIElement>().ToList())
            {
                NewControls.Remove(element);

                this.newPanel.Children.Add(element);
            }
        }
    }
}

And in the other control or window:

xmlns:local="clr-namespace:WpfApplication1"
...
<local:BaseControl>
    <TextBlock>I'm from new</TextBlock>
</local:BaseControl>

Not sure it perfectly fits your needs but may serve as a good base.

Here my solution.

My UserControl:

<UserControl x:Class="ucFancyMenu" x:Name="MySelf"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid>
        <Label Height="30" VerticalAlignment="Top" Background="#F0F">So Fancy</Label>
        <ItemsControl Margin="0 30 0 0" ItemsSource="{Binding ElementName=MySelf, Path=Items}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
        </ItemsControl>
    </Grid>
</UserControl>

The UserControl Class:

<Markup.ContentProperty("Items")> _
Public Class ucFancyMenu

    Public Property Items As New List(Of UIElement)

End Class

How to use it in other Xamls:

<Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid>

        <local:ucFancyMenu>
            <Button>FancyBtn 1</Button>
            <Button>FancyBtn 2</Button>
            <Button>FancyBtn 3</Button>
            <Button>FancyBtn 4</Button>
            <Button>FancyBtn 5</Button>
            <Button>FancyBtn 6</Button>
            <Button>FancyBtn 7</Button>
        </local:ucFancyMenu>

    </Grid>
</Window>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM