WPF - 如何将其他控件传入我的UserControl?

时间:2011-07-22 16:57:23

标签: wpf xaml mvvm user-controls itemscontrol

基本上,我希望我的UserControl能够接受一种ItemsControl类型,以便我的XAML看起来像这样:

<my:MyControl DataContext="{Binding InnerViewModel}">
    <ItemsControl ... />
</my:MyControl>

那样,MyControl会显示自定义Items控件和其他控件吗?

1 个答案:

答案 0 :(得分:6)

首先注意几点:

  1. UserControl是一种ContentControl。这意味着您无法将子元素传递给UserControl。您可以覆盖内容,但这对于您想要完成的内容来说毫无结果。
  2. 如果您想要一个包含 SINGLE 子元素的控件,那么您正在寻找Decorator类。
  3. 如果您想要一个包含 MULTIPLE 子元素的控件,那么您正在寻找ItemsControl类。
  4. 所以,基本上你做错了。话虽这么说,有几种方法可以实现你想要的。您可以简单地使用ItemsControl并使用您自己的模板覆盖模板。您还可以创建一个继承自ItemsControl或Decorator的CustomControl。

    覆盖模板(作为样式)将是更简单的方法,所以我的建议就是这样做,除非你非常精通如何正确创建WPF自定义控件

    如果您选择使用自定义控件,看起来您可能希望将其作为装饰器(只是猜测您需要一个孩子)。令人讨厌的部分是,要真正创建一个写得很好的WPF自定义控件,你必须拥有一些非常好的技能。例如,Border是一种包含少量DependencyProperty属性的装饰器。该模板附带了PresentationFramework.dll(我认为),因此它具有一些默认的外观。边框(自定义控件)不是 难以编写。当你想要实际拥有交互逻辑时,非常烦人的是什么。您需要进行检查和平衡以确保从模板中检索控件引用。然后,只有这样,如果引用不为null,你可以继续你的逻辑。基本上,假设您编写了一种自定义控件,它有2个按钮来执行逻辑,并且您提供了一个默认模板,其中按钮被命名为“按钮1”和“按钮2”。你不能只从模板中拉出按钮1和按钮2,并期望它们在那里;有人可以轻松覆盖您的默认模板并删除按钮1和按钮2,使您的自定义控件无用(非常多)。如果您编码时没有考虑到这些情况,那么可怕的是什么。你的自定义控件会遇到NullReferenceException。更不用说你必须连接以允许命令绑定PER按钮,你还应该为每个按钮提供routedevent。基本上,自定义控件可能对您想要做的事情(可能)有点过多。

    我可能是错的,你可能超级熟练并知道如何制定自定义控件。或者,更好的是,您可能只想通过一种简单的方式来装饰您的ItemsControl,并在其顶部添加横幅?我不知道,但我相信你会这样做:)。


    总的来说,我将介绍如何覆盖ItemsControl模板。这是一个示例:

    <Window x:Class="Sample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Width="640" Height="480">
        <Window.Resources>
            <Style x:Key="ItemsControlStyle1" TargetType="{x:Type ItemsControl}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ItemsControl}">
                            <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
                                <StackPanel Orientation="Vertical">
                                    <TextBlock Text="A HEADER!" />
                                    <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                                </StackPanel>
                            </Border>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Window.Resources>
    
        <Grid x:Name="LayoutRoot">
            <ItemsControl Style="{DynamicResource ItemsControlStyle1}" />
        </Grid>
    </Window>