如何创建包含占位符以供以后使用的 WPF 用户控件 [英] How to create WPF usercontrol which contains placeholders for later usage

查看:30
本文介绍了如何创建包含占位符以供以后使用的 WPF 用户控件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最好通过例子来提问.假设我有使用此控件的 UserControl 和 Window.

我想以这种方式设计这个控件(名为 MyControl)(这是科幻语法!):

<按钮>只是一个按钮</按钮><PlaceHolder 名称="place_holder/></网格>

并在设计我的窗口时以这种方式使用:

<MyControl/>

<MyControl><占位符><按钮>按钮 1</按钮></place_holder></我的控制>

<MyControl><占位符><按钮>按钮 1</按钮><按钮>按钮 2</按钮></place_holder></我的控制>

当然,我希望能够在 Window 中向 MyControl 添加更多元素.因此,在某种程度上,它应该作为容器工作(如 Grid、StackPanel 等).位置将在 UserControl 中定义(在此示例中,在按钮只是一个按钮"之后),但要添加的内容(哪些元素)将在 Window 中定义(使用 UserControl -- MyControl --).

我希望这很清楚我想要实现的目标.重点是在设计Window的时候使用XAML,所以我的类应该不会比其他控件差.

现在,最大的问题是——怎么做?

备注:样式超出范围.我要做的就是在设计 Window 时(而不是在设计 MyControl 时)将我想要的任何控件添加到 MyControl.

解决方案

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"名称="控制"><网格><按钮>只是一个按钮</按钮><ContentControl Content="{绑定 PlaceHolder1, ElementName=control}"/></网格></用户控制>

公共部分类 MyUserControl2 : UserControl{公共静态只读 DependencyProperty PlaceHolder1Property =DependencyProperty.Register("PlaceHolder1", typeof(object), typeof(MyUserControl2), new UIPropertyMetadata(null));公共对象 PlaceHolder1{获取{返回(对象)GetValue(PlaceHolder1Property);}设置 { SetValue(PlaceHolder1Property,值);}}公共 MyUserControl2(){初始化组件();}}

<uc:MyUserControl2><uc:MyUserControl2.PlaceHolder1><TextBlock 文本="测试"/></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"名称="控制"><网格><按钮>只是一个按钮</按钮><ItemsControl Name="_itemsControl" ItemsSource="{Binding ItemsSource, ElementName=control}"/></网格></用户控制>

[ContentProperty("Items")]公共部分类 MyUserControl2:UserControl{公共静态只读 DependencyProperty ItemsSourceProperty =ItemsControl.ItemsSourceProperty.AddOwner(typeof(MyUserControl2));公共 IEnumerable ItemsSource{获取 { 返回 (IEnumerable)GetValue(ItemsSourceProperty);}设置 { SetValue(ItemsSourceProperty, value);}}公共 ItemCollection 项目{得到 { 返回 _itemsControl.Items;}}公共 MyUserControl2(){初始化组件();}}

<uc:MyUserControl2><TextBlock 文本="测试"/><TextBlock 文本="测试"/></uc:MyUserControl2>

使用 UserControls,您可以决定公开内部控件的某些属性;除了 ItemsSource 之外,可能还想公开 ItemsControl.ItemTemplate 之类的属性,但这一切都取决于你想如何使用它,如果你只是设置 >Items 那么你就不一定需要这些了.<​​/p>

I'd better ask the question by example. Let's say I have UserControl and Window which uses this control.

I would like to design this control (named MyControl) in such way (this is sci-fi syntax!):

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

and use in such ways when designing my Window:

<MyControl/>

or

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

or

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

Of course I would like to have ability to add even more elements to MyControl in Window. So, in a way it should work as container (like Grid, StackPanel, and so on). The placement would be defined in UserControl (in this example after button "Just a button") but what to add (what elements) would be defined in Window (where UserControl -- MyControl -- is used).

I hope this is clear what I would like to achieve. The key point is using XAML when designing Window, so my class should be no worse than other controls.

Now, the big QUESTION is -- how to do it?

Remarks: styling is out of scope. All I want to do is add any controls I want to MyControl when designing Window (not when designing MyControl).

解决方案

ContentControls & ItemsControls are good for this, you can bind them to a property of your UserControl or expose them.

Using a ContentControl (for placeholders in multiple disconnected places):

<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 (for collections in one place)

<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>

With UserControls you can decide to expose certain properties of internal controls; besides the ItemsSource one probably would want to also expose properties like the ItemsControl.ItemTemplate, but it all depends on how you want to use it, if you just set the Items then you do not necessarily need any of that.

这篇关于如何创建包含占位符以供以后使用的 WPF 用户控件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆