首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何创建具有命名内容的WPF UserControl

如何创建具有命名内容的WPF UserControl
EN

Stack Overflow用户
提问于 2009-04-15 11:41:25
回答 10查看 43.9K关注 0票数 110

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

然而,我也需要控件能够容纳可以命名的内容。我尝试了以下几种方法:

代码语言:javascript
复制
<UserControl.ContentTemplate>
    <DataTemplate>
        <Button>a reused button</Button>
        <ContentPresenter Content="{TemplateBinding Content}"/>
        <Button>a reused button</Button>
    </DataTemplate>
</UserControl.ContentTemplate>

但是,似乎放在用户控件中的任何内容都不能命名。例如,如果我以以下方式使用控件:

代码语言:javascript
复制
<lib:UserControl1>
     <Button Name="buttonName">content</Button>
</lib:UserControl1>

我收到以下错误:

无法对元素“Button”设置名称属性值“”buttonName“”。“”“‘Button”位于元素“UserControl1”的作用域中,该元素在另一个作用域中定义时已注册了一个名称。

如果我删除了buttonName,它就会编译,但是我需要能够命名内容。我如何才能做到这一点?

EN

回答 10

Stack Overflow用户

回答已采纳

发布于 2009-04-16 19:58:03

当使用XAML时,这似乎是不可能的。当我实际拥有所需的所有控件时,自定义控件似乎有点夸张,但只需要用一点逻辑将它们组合在一起,并允许命名内容。

正如mackenir建议的那样,JD's blog上的解决方案似乎有最好的折衷方案。扩展JD的解决方案以允许控件仍然在XAML中定义的一种方法可能如下所示:

代码语言:javascript
复制
    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;           
    }

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

票数 22
EN

Stack Overflow用户

发布于 2010-08-05 17:28:49

答案是不要使用UserControl来做这件事。

创建一个扩展ContentControl的类

代码语言:javascript
复制
public class MyFunkyControl : ContentControl
{
    public static readonly DependencyProperty HeadingProperty =
        DependencyProperty.Register("Heading", typeof(string),
        typeof(MyFunkyControl), new PropertyMetadata(HeadingChanged));

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

    public string Heading { get; set; }
}

然后使用样式指定内容

代码语言:javascript
复制
<Style TargetType="control:MyFunkyControl">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="control:MyFunkyControl">
                <Grid>
                    <ContentControl Content="{TemplateBinding Content}"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

最后--使用它

代码语言:javascript
复制
<control:MyFunkyControl Heading="Some heading!">            
    <Label Name="WithAName">Some cool content</Label>
</control:MyFunkyControl>
票数 52
EN

Stack Overflow用户

发布于 2011-08-24 04:11:00

我使用的另一个替代方法是只在Loaded事件中设置Name属性。

在我的例子中,我有一个相当复杂的控件,我不想在代码隐藏中创建它,它为某些行为寻找具有特定名称的可选控件,因为我注意到可以在DataTemplate中设置名称,所以我想我也可以在Loaded事件中这样做。

代码语言:javascript
复制
private void Button_Loaded(object sender, RoutedEventArgs e)
{
    Button b = sender as Button;
    b.Name = "buttonName";
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/751325

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档