【问题标题】:WPF - Hosting content inside a UserControlWPF - 在用户控件中托管内容
【发布时间】:2012-05-12 17:13:06
【问题描述】:

我正在尝试创建一个具有两行 Grid 的用户控件。 第一行用于标题,第二行用于将在用户控件之外定义的内容,例如我们示例中的Button

不知怎的,我没有让它工作。

UserControl1 xaml:

  <Grid Background="LightBlue">
    <Grid.RowDefinitions>
        <RowDefinition Height="50" />
        <RowDefinition Height="*" />
    </Grid.RowDefinitions>
    <TextBlock Text="Title" FontSize="30" Margin="10,0,0,0"/>
</Grid>

主窗口 xaml:

 <Grid>
    <local:UserControl1>
        <Button>Click me</Button>
    </local:UserControl1>
</Grid>

下面的图片应该可以解释我的问题是什么:

【问题讨论】:

    标签: wpf user-controls


    【解决方案1】:

    以下代码

    <local:UserControl1>
        <Button>Click me</Button>
    </local:UserControl1>
    

    表示您将UserControl1 的Content 属性设置为该按钮。这个按钮只是替换了UserControls1 的标记。所以你在 UserControl1.xaml 中的所有东西都不再存在了。

    编辑

    如果您希望您的 UserControl 托管一些将在其外部设置的标记,您可以向其添加 DependencyProperty,例如:

        /// <summary>
        /// Gets or sets additional content for the UserControl
        /// </summary>
        public object AdditionalContent
        {
            get { return (object)GetValue(AdditionalContentProperty); }
            set { SetValue(AdditionalContentProperty, value); }
        }
        public static readonly DependencyProperty AdditionalContentProperty =
            DependencyProperty.Register("AdditionalContent", typeof(object), typeof(UserControl1),
              new PropertyMetadata(null));
    

    并在它的标记中添加一些元素来承载额外的内容。这是扩展您提供的标记的示例:

    <UserControl ... Name="userControl">
        <Grid Background="LightBlue">
            <Grid.RowDefinitions>
                <RowDefinition Height="50" />
                <RowDefinition Height="*" />
            </Grid.RowDefinitions>
    
            <TextBlock Text="Title" FontSize="30" Margin="10,0,0,0"/>
            <ContentPresenter Content="{Binding AdditionalContent, ElementName=userControl}" />
        </Grid>
    </UserControl>
    

    现在你可以如下使用它:

    <local:UserControl1>
        <local:UserControl1.AdditionalContent>
            <Button>Click me</Button>
        </local:UserControl1.AdditionalContent>
    </local:UserControl1>
    

    【讨论】:

    • 为什么要使用额外的依赖属性而不只是替换控件模板并绑定到内容属性?
    • 我同意你的看法。我刚刚发布了我的答案,就看到了你的答案。是我投票给你的
    • 为什么它不起作用的解释很好,但我发现@blindmeis 的回答更有帮助。
    • 您可以简单地在类上使用[ContentProperty("AdditionalContent")] 属性,而不是使用&lt;local:UserControl1.AdditionalContent&gt;,然后就可以在控件的内容中包含自定义控件。这很棒,因为没有人可以通过意外设置内容而不是AdditionalContent来破坏它。
    • 什么是CalibrationPoint?智能无法找到该类的可能解决方案,这是一些自定义的东西吗? [[ 编辑]] 抱歉我没有检查方法Register 参数。我觉得应该改成UserControl1来编译。
    【解决方案2】:

    你必须设置ControlTemplate:

    <UserControl>
    <UserControl.Resources>
        <Style TargetType="{x:Type local:UserControl1}">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type local:UserControl1}">
                        <Grid Background="LightBlue">
                            <Grid.RowDefinitions>
                                <RowDefinition Height="50" />
                                <RowDefinition Height="*" />
                            </Grid.RowDefinitions>
                            <TextBlock Grid.Row="0" Text="Title" FontSize="30" Margin="10,0,0,0"/>
                            <ContentPresenter Grid.Row="1" />
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </UserControl.Resources>
    </UserControl>
    

    【讨论】:

    • 您是否有理由通过UserControl.Resources/Style 设置它,而不是将ControlTemplate 作为UserControl.Template 的内容?
    • 不幸的是,似乎不支持设置 UserControlTemplate 属性:social.msdn.microsoft.com/forums/silverlight/en-US/…
    • UserControl.Template 为我工作。我使用 TargetType="{x:Type UserControl}"。
    • 谢谢你。
    • 设置控制模板会禁止在您设置的任何内容中使用 x:Name。在 .Net 4.7 wpf 应用程序中测试。 Namescope 显然已经设置好了。
    【解决方案3】:

    您可以模板化用户控件以添加额外的视觉效果,例如TextBlock

    <UserControl>
    <UserControl.Style>
      <Style TargetType="{x:Type UserControl}">
        <Setter Property="Template">
          <Setter.Value>
            <ControlTemplate>              
              <Grid Background="LightBlue"> 
              <Grid.RowDefinitions> 
                <RowDefinition Height="50" /> 
                <RowDefinition Height="*" /> 
              </Grid.RowDefinitions> 
              <TextBlock Text="Title" FontSize="30" Margin="10,0,0,0"/> 
              <ContentPresenter Grid.Row="1" Content="{TemplateBinding Content}"  />
              </Grid> 
            </ControlTemplate>
          </Setter.Value>
        </Setter>
      </Style>
    </UserControl.Style>
    <Button>
      Click me!
    </Button>
    </UserControl>
    

    【讨论】:

    • 使用&lt;ControlTemplate TargetType="{x:Type UserControl}"&gt; 使其在资源字典中工作
    • 我创建了一个需要包含内容的新用户控件。这是唯一一个似乎可以正常工作的解决方案,而不会在实施过程中或以后出现大量其他问题。例如。 @blindmeis 解决方案在控件本身的设计器中没有显示任何视觉效果。仅在使用新控件的控件的设计器中。仍然存在设置为新控件内容的控件不能具有名称属性的问题。
    【解决方案4】:

    使用模板与

    而不是使用 Content Presenter

    所以放这个:

    <UserControl.Style>
            <Style TargetType="{x:Type UserControl}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type UserControl}" >
                              <Grid Background="LightBlue"> 
                               <Grid.RowDefinitions> 
                                <RowDefinition Height="50" /> 
                                <RowDefinition Height="*" /> 
                              </Grid.RowDefinitions> 
                               <TextBlock Text="Title" FontSize="30" Margin="10,0,0,0"/> 
    
                            <ContentControl  Grid.Row="1" Content="{TemplateBinding Content}"  />
    
                            </Grid> 
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </UserControl.Style>
    

    到你的用户控件

    【讨论】:

    • 将模板与 ContentControl 一起使用,而不是使用 ContentPresenter - 为什么?
    • 最好在模板中使用 ContentPresenter,参见stackoverflow.com/a/1288353/991267
    猜你喜欢
    • 1970-01-01
    • 2012-03-27
    • 1970-01-01
    • 1970-01-01
    • 2013-05-29
    • 1970-01-01
    • 2013-02-21
    • 2014-06-23
    • 1970-01-01
    相关资源
    最近更新 更多