如何使用NAMED内容创建WPF UserControl

Rya*_*yan 90 c# wpf xaml user-controls controls

我有一组带有附加命令和逻辑的控件,它们以相同的方式不断重用.我决定创建一个包含所有常用控件和逻辑的用户控件.

但是我还需要控件才能保存可以命名的内容.我尝试了以下方法:

<UserControl.ContentTemplate>
    <DataTemplate>
        <Button>a reused button</Button>
        <ContentPresenter Content="{TemplateBinding Content}"/>
        <Button>a reused button</Button>
    </DataTemplate>
</UserControl.ContentTemplate>
Run Code Online (Sandbox Code Playgroud)

但是,似乎无法命名放置在用户控件内的任何内容.例如,如果我以下列方式使用控件:

<lib:UserControl1>
     <Button Name="buttonName">content</Button>
</lib:UserControl1>
Run Code Online (Sandbox Code Playgroud)

我收到以下错误:

无法在元素"Button"上设置Name属性值"buttonName".'Button'属于元素'UserControl1'的范围,在另一个范围内定义时,已经注册了一个名称.

如果我删除buttonName,然后编译,但我需要能够命名内容.我怎样才能做到这一点?

Syb*_*and 41

答案是不使用UserControl来执行此操作.

创建一个扩展ContentControl的类

public class MyFunkyControl : ContentControl
{
    public static readonly DependencyProperty HeadingProperty =
        DependencyProperty.Register("Heading", typeof(string),
        typeof(HeadingContainer), new PropertyMetadata(HeadingChanged));

    private static void HeadingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ((HeadingContainer) d).Heading = e.NewValue as string;
    }

    public string Heading { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然后使用样式指定内容

<Style TargetType="control:MyFunkyControl">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="control:MyFunkyContainer">
                <Grid>
                    <ContentControl Content="{TemplateBinding Content}"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
Run Code Online (Sandbox Code Playgroud)

最后 - 使用它

<control:MyFunkyControl Heading="Some heading!">            
    <Label Name="WithAName">Some cool content</Label>
</control:MyFunkyControl>
Run Code Online (Sandbox Code Playgroud)

  • @greenoldman @Badiboy我想我知道为什么它不适合你.你可能刚刚从`UserControl`改变了现有的代码来继承`ContentControl`.要解决,只需添加新类(**不是**XAML与CS).然后它(希望)会起作用.如果你愿意,我已经创建了一个小的[VS2010解决方案](http://www.mediafire.com/download/vxm1a1d3uxurc8e/ControlWithNamedContentTest1000.rar) (8认同)
  • 嗯,它有点奇怪它适合你,因为我试图应用这种方法,在我的情况下,我仍然得到这个臭名昭着的错误. (3认同)
  • 我猜“HeadingContainer”和“MyFunkyContainer”应该是“MyFunkyControl”?! (3认同)
  • 我发现这实际上是最舒适的解决方案,因为您可以使用设计器在普通的UserControl中充实ControlTemplate,并将其转换为具有相关控件模板的样式. (2认同)
  • 跟我一样:没影响.:( (2认同)
  • 许多年后,我希望我能再次投票:) (2认同)
  • “&lt;Style&gt;”是在“MyFunkyControl”中设置的还是在使用它的控件中设置的? (2认同)

Rya*_*yan 18

使用XAML时似乎无法做到这一点.当我实际拥有我需要的所有控件时,自定义控件似乎是一种矫枉过正,但只需要将它们与一小部分逻辑组合在一起并允许命名内容.

作为mackenir的JD博客解决方案表明,似乎有最好的妥协.扩展JD的解决方案以允许仍然在XAML中定义控件的方法可以如下:

    protected override void OnInitialized(EventArgs e)
    {
        base.OnInitialized(e);

        var grid = new Grid();
        var content = new ContentPresenter
                          {
                              Content = Content
                          };

        var userControl = new UserControlDefinedInXAML();
        userControl.aStackPanel.Children.Add(content);

        grid.Children.Add(userControl);
        Content = grid;           
    }
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,我创建了一个名为UserControlDefinedInXAML的用户控件,它与使用XAML的任何普通用户控件一样定义.在我的UserControlDefinedInXAML中,我有一个名为aStackPanel的StackPanel,我希望在其中显示我的命名内容.