属性已被“FrameworkElement”注册。

25

我正在编写两个依赖属性,但在VS11的设计窗口中一直收到“[属性]已由‘FrameworkElement’注册”错误。以下是我的代码片段:

        public static readonly DependencyProperty IsEditingNumberProperty =
        DependencyProperty.Register("IsEditingNumbers", typeof(bool), typeof(FrameworkElement),
        new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.AffectsRender));

问题似乎在第三个参数上(owner parameter typeof(FrameworkElement))。如果我将第三个参数设置为包含两个依赖属性的类,则错误消失,但我无法直接从xaml中使用这些属性。在使用之前,我需要为每个依赖属性添加所有权。

实际上,它可以正确渲染,但仅当我首次打开它时才会如此。第一次渲染后立即会给我一个异常。在运行时,它似乎完美地工作。

我是否做错了什么,有没有办法摆脱这个烦人的错误?

---- 编辑 -----

这是我的自定义类(包括2个Dependency Properties):

public partial class EditableTextBox : UserControl
{
    #region Dependency Properties
    public static readonly DependencyProperty IsEditingNumberProperty =
        DependencyProperty.Register("IsEditingNumber", typeof(bool), typeof(FrameworkElement),
        new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.AffectsRender));

    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register("Text", typeof(string), typeof(FrameworkElement),
        new FrameworkPropertyMetadata("0", FrameworkPropertyMetadataOptions.AffectsRender) 
        { 
            CoerceValueCallback = new CoerceValueCallback((sender,value) =>
                {
                    return expressionRestaraint.Match((string)value).Value;
                })
        });
    #endregion

    public static Regex expressionRestaraint = new Regex("[-a-zA-z0-9+*.\\(\\)\\[\\]\\{\\}]*");

    public string Text
    {
        get { (string)GetValue(TextProperty); }
        set 
        { 
            SetValue(TextProperty, value);
            tbxValue.Text = (string)GetValue(TextProperty);
        }
    }

    public bool IsEditingNumber
    {
        get 
        { 
            return (bool)GetValue(IsEditingNumberProperty); 
        }
        set 
        {
            bool old = (bool)GetValue(IsEditingNumberProperty);
            if (old != value)
            {
                if (!value)
                    stopEditing();
                else
                    startEditing();

                SetValue(IsEditingNumberProperty, value);
            }
        }
    } . . .

在主类中使用:

<Window x:Class="VisualMathExpression.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:edit="clr-namespace:VisualMathExpression.EditableTextBox"
    xmlns:all="clr-namespace:VisualMathExpression"
    Title="MainWindow" Height="350" Width="525">
<StackPanel>
    <edit:EditableTextBox HorizontalAlignment="Center" VerticalAlignment="Center"
                          Text="af" IsEditingNumber="True" /> . . .

--- 编辑 --- 包装器已修复(问题是当所有权属于声明的类时,导致XAML属性不会更改)

    public partial class EditableTextBox : UserControl
{
    #region Dependency Properties
    public static readonly DependencyProperty IsEditingNumberProperty =
        DependencyProperty.Register("IsEditingNumber", typeof(bool), typeof(EditableTextBox),
        new FrameworkPropertyMetadata(true, FrameworkPropertyMetadataOptions.AffectsRender) 
        { 
            PropertyChangedCallback = new PropertyChangedCallback((sender, arg) =>
                {
                    EditableTextBox ed = sender as EditableTextBox;
                    if (!(bool)arg.NewValue)
                        ed.stopEditing();
                    else
                        ed.startEditing();
                }),
        });

    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register("Text", typeof(string), typeof(EditableTextBox),
        new FrameworkPropertyMetadata("0", FrameworkPropertyMetadataOptions.AffectsRender) 
        { 
            PropertyChangedCallback = new PropertyChangedCallback((sender,arg) =>
                {
                    EditableTextBox ed = sender as EditableTextBox;
                    ed.tbxValue.Text = arg.NewValue as string;
                }),
            CoerceValueCallback = new CoerceValueCallback((sender,value) =>
                {
                    return expressionRestaraint.Match((string)value).Value;
                })
        });
    #endregion

    public static Regex expressionRestaraint = new Regex("[-a-zA-z0-9+*.\\(\\)\\[\\]\\{\\}]*");

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    public bool IsEditingNumber
    {
        get { return (bool)GetValue(IsEditingNumberProperty); }
        set { SetValue(IsEditingNumberProperty, value); }
    }

数字不一致是违反指南的,但可能不是原因。 - H H
我实际上是有意更改了那个,以查看它是否与包装器发生冲突......问题在一个构建中消失了,然后问题又再次出现。 - rbtLong
刚看到您取消了答案的采纳。有什么特别的原因吗? - Clemens
1个回答

59
DependencyProperty.Register 方法的第三个参数 ownerType 必须是声明该属性的类。
如果您的类是 MyClass,则声明应该如下所示:
public class MyClass : DependencyObject
{
    public static readonly DependencyProperty IsEditingNumberProperty =
        DependencyProperty.Register(
            "IsEditingNumber", typeof(bool), typeof(MyClass), ...);

    // CLR wrapper
    public bool IsEditingNumber
    {
        get { return (bool)GetValue(IsEditingNumberProperty); }
        set { SetValue(IsEditingNumberProperty, value); }
    }
}

好的,但是如果我在Main方法中使用MyClass,那么xaml属性将不起作用,除非我在静态构造函数中添加MyClass.IsEditingNumberProperty.AddOwner(Main)的所有权。我必须为每个依赖属性都这样做吗?还有其他方法吗? - rbtLong
我不太明白你所说的“xaml属性无效”是什么意思。你可能只是忘记为你的依赖属性添加CLR包装器了吗?此外,声明该属性的类必须派生自DependencyObject(或派生类),除非它是一个附加属性。请参见编辑后的答案。 - Clemens
在CLR包装器中,除了使用GetValue/SetValue之外,您绝不能做任何其他事情。当在XAML中使用属性时,它们不会被调用。相反,请使用PropertyChangedCallback(通过元数据)。请参见此处的“实现包装器”部分:http://msdn.microsoft.com/en-us/library/ms753358.aspx#checklist。 - Clemens
你仍然使用 typeof(FrameworkElement) 作为所有者类型。这是错误的。你必须使用 typeof(EditableTextBox) - Clemens
1
你可以这样做。第一个参数是对你的EditableTextBox实例的引用。只需将DependencyObject强制转换为EditableTextBox即可。请参见此处 - Clemens
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接