如何在现有控件上创建依赖关系属性?

发布于 2024-09-27 06:27:29 字数 521 浏览 0 评论 0原文

我已经阅读依赖属性几天了,并了解它们如何检索值,而不是像 CLR 属性中那样设置/获取它们。如果我错了,请随时纠正我。

据我了解,从 DependencyObject 派生的所有 WPF 控件(如 TextBlock、Button 等)也将包含依赖属性来存储其值,而不是使用 CLR 属性。这样做的优点是在使用动画的情况下覆盖本地值,或者在根本没有设置本地值的情况下继承值等。

我现在正在尝试提供一些示例来创建和使用我自己的 dp。

1) 是否可以在现有 WPF 控件上创建我自己的依赖属性?假设我想要 WPF Textblock 类上整数类型的依赖属性?或者我是否必须创建一个从 TextBlockBase 派生的新类才能在上面创建我的依赖属性?

2) 在任何一种情况下,假设我已经在 WPF 文本块类上创建了依赖属性。现在我想通过将标签的内容绑定到 TextBlock 的依赖属性来利用它。这样标签总是显示 TextBlock 的 dp 的实际值,无论它是继承的还是本地设置的。

希望有人能帮助我解决这两个例子...... 非常感谢, 卡韦

I have been reading on Dependency properties for a few days and understand how they retrieve the value rather than to set/get them as in CLR properties. Feel free to correct me if I am wrong.

From my understanding all WPF controls like a TextBlock, Button etc that derive from DependencyObject would also contain dependency properties to store their values, instead of using CLR properties. This has the advantage of overriding local values in case animations are used, or inherit values if no local value is set at all etc.

I am now trying to come up with some samples to create and use my own dp.

1) Is it possible to create my own dependency property on an existing WPF control? Let say I would like a dependency property of type integer on WPF Textblock class ? Or do i have to create a new class derived from TextBlockBase in order to create my dependency property above in there?

2) In either case, let say I have created a dependency property on a WPF textblock class. Now I would like to utilize it by binding the content of label to that dependency property of the TextBlock. So that the label would always show the actual value of TextBlock's dp, no matter if its inherited or set locally.

Hopefully someone can help me with these two examples...
Many Thanks,
Kave

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

恏ㄋ傷疤忘ㄋ疼 2024-10-04 06:27:29

您可以为其使用附加属性

定义您的属性 MyInt:


namespace WpfApplication5
{
    public class MyProperties
    {
        public static readonly System.Windows.DependencyProperty MyIntProperty;

        static MyProperties()
        {
            MyIntProperty = System.Windows.DependencyProperty.RegisterAttached(
                "MyInt", typeof(int), typeof(MyProperties));
        }

        public static void SetMyInt(System.Windows.UIElement element, int value)
        {
            element.SetValue(MyIntProperty, value);
        }

        public static int GetMyInt(System.Windows.UIElement element)
        {
            return (int)element.GetValue(MyIntProperty);
        }
    }
}

绑定标签内容:


<Window x:Class="WpfApplication5.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication5"
    Title="Window1" Height="300" Width="300">
    <Grid>
        <Label Margin="98,115,51,119" Content="{Binding Path=(local:MyProperties.MyInt), RelativeSource={x:Static RelativeSource.Self}}" local:MyProperties.MyInt="42"/>
    </Grid>
</Window>

You can use attached properties for it.

Define your property MyInt:


namespace WpfApplication5
{
    public class MyProperties
    {
        public static readonly System.Windows.DependencyProperty MyIntProperty;

        static MyProperties()
        {
            MyIntProperty = System.Windows.DependencyProperty.RegisterAttached(
                "MyInt", typeof(int), typeof(MyProperties));
        }

        public static void SetMyInt(System.Windows.UIElement element, int value)
        {
            element.SetValue(MyIntProperty, value);
        }

        public static int GetMyInt(System.Windows.UIElement element)
        {
            return (int)element.GetValue(MyIntProperty);
        }
    }
}

Bind label content:


<Window x:Class="WpfApplication5.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfApplication5"
    Title="Window1" Height="300" Width="300">
    <Grid>
        <Label Margin="98,115,51,119" Content="{Binding Path=(local:MyProperties.MyInt), RelativeSource={x:Static RelativeSource.Self}}" local:MyProperties.MyInt="42"/>
    </Grid>
</Window>
青衫负雪 2024-10-04 06:27:29

您无法将 DependencyProperties 添加到现有类型。虽然您可以使用 AttachedProperty,但使用它和派生新类型背后的逻辑完全不同。

对于你的情况,我建议派生新类型。主要是因为你的逻辑是与这个类型绑定的。这是继承背后的基础,不受依赖属性的约束。

对于 AttachedProperty,您仅向另一个对象提供不同对象中值的感知。像 Grid.Row 这样的东西让 Grid 知道它的子级以及它应该如何定位它。设置此属性的对象不知道任何事情。

You cant add DependencyProperties to existing type. While you can use AttachedProperty, logic behind using it and deriving new type is completly different.

In your case I would recomend to derive new type. Mainly because your logic is bound with this type. This is basic behind inheritance and is not bound with Dependency properties.

In case of AttachedProperty you are only giving another object awerness of values in different object. Something like Grid.Row is giving Grid awerness of its child and how it should position it. Object where this property is set is not aware of anything.

木格 2024-10-04 06:27:29

以下是 Run 元素的 ovveride 示例:

using System;
using System.Windows;
using System.Windows.Documents;

namespace MyNameSpace.FlowDocumentBuilder
{
    public class ModifiedRun : Run
    {
        static DateRun()
        {
            TextProperty.OverrideMetadata(typeof(DateRun),new FrameworkPropertyMetadata(string.Empty,FrameworkPropertyMetadataOptions.Inherits,null,CoerceValue));
        }

        private static object CoerceValue(DependencyObject d, object basevalue)
        {
            return "AAAAAAAA";
        }
    }
}

相应的 XAML 为:

<FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                      ColumnWidth="400"
                      FontSize="14"
                      FontFamily="Arial"
xmlns:local="clr-namespace:MyNameSpace.FlowDocumentBuilder;assembly=MyNameSpace.FlowDocumentBuilder"
>

<Paragraph><local:ModifiedRun Text="BBBBBBBBBB"/></Paragraph>

</FlowDocument>

Here is an example on an ovveride of the Run element:

using System;
using System.Windows;
using System.Windows.Documents;

namespace MyNameSpace.FlowDocumentBuilder
{
    public class ModifiedRun : Run
    {
        static DateRun()
        {
            TextProperty.OverrideMetadata(typeof(DateRun),new FrameworkPropertyMetadata(string.Empty,FrameworkPropertyMetadataOptions.Inherits,null,CoerceValue));
        }

        private static object CoerceValue(DependencyObject d, object basevalue)
        {
            return "AAAAAAAA";
        }
    }
}

An the corresponding XAML is:

<FlowDocument xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                      ColumnWidth="400"
                      FontSize="14"
                      FontFamily="Arial"
xmlns:local="clr-namespace:MyNameSpace.FlowDocumentBuilder;assembly=MyNameSpace.FlowDocumentBuilder"
>

<Paragraph><local:ModifiedRun Text="BBBBBBBBBB"/></Paragraph>

</FlowDocument>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文