Как создать WPF usercontrol, который содержит заполнители для последующего использования - PullRequest
35 голосов
/ 22 апреля 2011

Я бы лучше задал вопрос на примере. Допустим, у меня есть UserControl и Window, который использует этот элемент управления.

Я хотел бы спроектировать этот элемент управления (названный MyControl) таким образом (это синтаксис научной фантастики!):

<Grid>
  <Button>Just a button</Button>
  <PlaceHolder Name="place_holder/>
</Grid> 

и используйте при проектировании моего окна:

<MyControl/>

или

<MyControl>
  <place_holder>
    <Button>Button 1</Button>
  </place_holder>
</MyControl> 

или

<MyControl>
  <place_holder>
    <Button>Button 1</Button>
    <Button>Button 2</Button>
  </place_holder>
</MyControl> 

Конечно, я хотел бы иметь возможность добавлять еще больше элементов в MyControl в Window. Таким образом, он должен работать как контейнер (например, Grid, StackPanel и т. Д.). Размещение будет определено в UserControl (в этом примере после кнопки «Просто кнопка»), но что добавить (какие элементы) будет определено в Window (где используется UserControl - MyControl -).

Надеюсь, это ясно, чего я хотел бы достичь. Ключевым моментом является использование XAML при разработке Window, поэтому мой класс должен быть не хуже других элементов управления.

Итак, большой ВОПРОС - как это сделать?

Замечания: стилизация выходит за рамки. Все, что я хочу сделать, это добавить любые элементы управления, которые я хочу, в MyControl при разработке Window (а не при разработке MyControl).

Ответы [ 2 ]

47 голосов
/ 22 апреля 2011

ContentControls & ItemsControls хороши для этого, вы можете привязать их к свойству UserControl или предоставить их.

Использование ContentControl (для заполнителей в нескольких отключенных местах):

<UserControl x:Class="Test.UserControls.MyUserControl2"
             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" 
             Name="control">
    <Grid>
        <Button>Just a button</Button>
        <ContentControl Content="{Binding PlaceHolder1, ElementName=control}"/>
    </Grid>
</UserControl>
public partial class MyUserControl2 : UserControl
{
    public static readonly DependencyProperty PlaceHolder1Property =
        DependencyProperty.Register("PlaceHolder1", typeof(object), typeof(MyUserControl2), new UIPropertyMetadata(null));
    public object PlaceHolder1
    {
        get { return (object)GetValue(PlaceHolder1Property); }
        set { SetValue(PlaceHolder1Property, value); }
    }

    public MyUserControl2()
    {
        InitializeComponent();
    }
}
<uc:MyUserControl2>
    <uc:MyUserControl2.PlaceHolder1>
        <TextBlock Text="Test"/>
    </uc:MyUserControl2.PlaceHolder1>
</uc:MyUserControl2>

ItemsControl-Version (для коллекций в одном месте)

<UserControl x:Class="Test.UserControls.MyUserControl2"
             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"
             Name="control">
    <Grid>
        <Button>Just a button</Button>
        <ItemsControl Name="_itemsControl" ItemsSource="{Binding ItemsSource, ElementName=control}"/>
    </Grid>
</UserControl>
[ContentProperty("Items")]
public partial class MyUserControl2 : UserControl
{
    public static readonly DependencyProperty ItemsSourceProperty = 
        ItemsControl.ItemsSourceProperty.AddOwner(typeof(MyUserControl2));
    public IEnumerable ItemsSource
    {
        get { return (IEnumerable)GetValue(ItemsSourceProperty); }
        set { SetValue(ItemsSourceProperty, value); }
    }

    public ItemCollection Items
    {
        get { return _itemsControl.Items; }
    }

    public MyUserControl2()
    {
        InitializeComponent();
    }
}
<uc:MyUserControl2>
    <TextBlock Text="Test"/>
    <TextBlock Text="Test"/>
</uc:MyUserControl2>

С помощью UserControls вы можете указать некоторые свойства внутренних элементов управления;кроме ItemsSource, возможно, вы захотите также выставить свойства, такие как ItemsControl.ItemTemplate, но все зависит от того, как вы хотите его использовать. Если вы просто установите Items, тогда вам не обязательно что-либо из этого.

21 голосов
/ 22 апреля 2011

Я думаю, что вы хотите установить ControlTemplate вашего UserControl с ContentPresenter, расположенным внутри (чтобы вы могли определить, где будет представлен контент).

Ваш пользовательский контроль пользователя:

<UserControl x:Class="TestApp11.UserControl1"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <UserControl.Template>
        <ControlTemplate>
            <StackPanel>
                <TextBlock Text="Custom Control Text Area 1" />
                <ContentPresenter Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}" />
                <TextBlock Text="Custom Control Text Area 2" />
            </StackPanel>
        </ControlTemplate>
    </UserControl.Template>
</UserControl>

Использование:

<Window x:Class="TestApp11.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:l="clr-namespace:TestApp11"
    Title="Window1" Height="250" Width="200">
    <StackPanel>
        <l:UserControl1>
            <Button Content="My Control's Content" />
        </l:UserControl1>
    </StackPanel>
</Window>

enter image description here

Если вам нужно несколько элементов в разделе контента, просто поместите их в контейнер, такой как сетка или панель стека:

<l:UserControl1>
    <StackPanel>
        <Button Content="Button 1" />
        <Button Content="Button 2" />
    </StackPanel>
</l:UserControl1>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...