【问题标题】:Chaining DependencyProperties链接依赖属性
【发布时间】:2012-01-20 10:59:57
【问题描述】:

假设我有一个自定义控件,它包装了另一个控件(例如 MyCustomButton)。我暴露了一个属性Content,它封装了内部控件:

    public object Content
    {
        get { return innerControl.Content; }
        set { innerControl.Content = value; }
    }

为了让消费者绑定到这个属性,我需要为它定义一个 DependencyProperty:

 public static DependencyProperty ContentProperty = DependencyProperty.Register("Content", typeof (object), typeof (MyCustomButton));

但现在我需要我的属性定义才能使用 GetValue/SetValue:

    public object Content
    {
        get { return GetValue(ContentProperty); }
        set { SetValue(ContentProperty, value); }
    }

所以我不再包装内部控件的值了。

我可以定义 PropertyMetadata 来处理 DependencyProperty 的 PropertyChanged 事件,但是我需要一堆管道代码来保持值同步并防止更改时无限循环。

更新:我不能只从 Button 派生,因为我的 UserControl 有各种其他问题。

有没有更好的方法来做到这一点?

【问题讨论】:

    标签: wpf xaml dependency-properties


    【解决方案1】:

    好吧,根据您使用用户控件包装按钮的具体原因,您可以定义一个从按钮继承的自定义控件。然后,您可以简单地覆盖您想要定义自定义控件行为的方法和属性,而不是包装按钮并公开您想要的包装方法和属性。这样,您将获得按钮的所有功能,而无需重新发明轮子。

    这里有一个谷歌链接可以引导你(我发现的第一个 - 有很多):http://knol.google.com/k/creating-custom-controls-with-c-net#

    如果用户控件有其他问题,这可能不是您的选择,但我提供此答案是因为您提到的唯一目的是包装按钮。如果所讨论的控件只是一种更具体的包装/继承控件(即您的情况下的按钮),我个人更倾向于创建自定义控件并继承而不是用户控件和包装。

    编辑:根据更新的问题...

    你可以按照这些思路做一些事情。这是您的用户控件客户端的 XAML:

    <Grid>
        <local:MyControl ButtonContent="Click Me!"/>
    </Grid>
    </Window>
    

    这是用户控件本身的 XAML:

     <UserControl x:Class="GuiScratch.MyControl"
                 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" 
                 xmlns:local="clr-namespace:GuiScratch"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300">
        <Grid>
    
            <StackPanel>
                <ContentControl Content="Asdf"/>
                <Button Content="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:MyControl}},Path=ButtonContent}"/>
            </StackPanel>
    
        </Grid>
    </UserControl>
    

    还有,下面是代码:

    public partial class MyControl : UserControl
    {
    
        public static readonly DependencyProperty ButtonContentProperty = 
        DependencyProperty.Register("ButtonContent", typeof(object), typeof(MyControl), 
        new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender));
    
        public object ButtonContent
        {
            get { return (object)GetValue(ButtonContentProperty); }
            set { SetValue(ButtonContentProperty, value); }
        }
    
        public MyControl()
        {
            InitializeComponent();
        }
    }
    

    因此,您根本不需要通过代码来处理绑定。您的客户端 XAML 绑定到您的依赖项属性,用户控件本身的 XAML 也是如此。以这种方式,它们共享依赖属性设置。我在我的小便签本中运行了这个,结果是(至少我的理解)你在找什么。主窗口将用户控件显示为带有文本“Asdf”的堆栈面板,然后是带有文本“Click Me!”的按钮

    【讨论】:

    • 用户控件有其他问题。更新的问题。
    • 您是否特别想使用用户控件的“内容”属性?如果没有,您总是可以公开不同的依赖属性并将用户控件中的某些内容绑定到它的值。
    • 我不在乎它叫什么。但我希望该属性的值专门绑定到内部控件上的某些东西。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-16
    • 2022-11-19
    • 2011-11-07
    • 2014-04-23
    相关资源
    最近更新 更多