覆盖在基类中定义的属性

19

我有一个情况,其中类层次结构是这样的:

   +---------------+
   | UIElement     |
   |---------------|                            +----------------------+
   | ...           |                            | My Windows Application
   | SomePropert{} |                            |----------------------|
   |               |<---+                       |+--------------------+|
   |               |    |                       ||MyUserControl       ||
   +---------------+    |                       ||--------------------||
         +--------------+-----+                 ||                    ||
         |FrameWorkElement    |                 |+--------------------+|
         |--------------------|                 |//Want to use         |
         |    ...             |<-+              |// SomeProperty;      |
         +--------------------+  |              |                      |
                     +-----------+-+            |                      |
                     |Control      |            |                      |
                     |-------------|            +----------------------+
                     |  ...        |<---+
                     +-------------+    |
                            +-----------+---+
                            | UserControl   |
                            |---------------|<---+
                            |  ...          |    |
                            +---------------+    |
                                      +----------+-------+
                                      | MyUserControl    |
                                      |------------------|
                                      | SomeProperty{}   |
                                      | //Want to override
                                      |                  |
                                      +------------------+

现在,在我的应用程序中(以及所有其他可以导出此MyUserControl的应用程序中),我可以设置由MyUserControl类处理而不是UIElementSomeProperty吗?

我现在正在通过创建一个指向MyUserControl对象并将其分配给我在xaml页面中添加的控件来实现这一点。所以现在看起来像这样:

MyUserControl newControl = new MyUserControl();
web = windowsPhoneControl11;  //windowsPhoneControll1 is the 
                              //one that I added from toolbox.
                              // i.e., mycustomecontrol added from toolbox.

现在由于我正在使用“new”,所以它被覆盖了。但是当我导出此控件时,我不能指望用户创建一个新对象并将其分配给在xaml页面中使用的控件。

那么,是否还有其他方式可以覆盖此属性,以便MyUserControl类处理该属性的赋值而不是UIElement类?我的意思是,让MyUserControl具有设置此属性的控制权,因为我需要检查某些值然后再进行分配。如果它不是期望的值,则需要将其设置为默认值。

PS:非常抱歉这个问题很长,但我无法更加精确地表达它,也找不到与此相关的其他问题。这是WindowsPhoneApp,而不是普通的Windows应用程序。


在提供的代码中,MyUserControl newControl = new MyUserControl(); 这行代码的含义是什么? - Tigran
2
ASCII图表获得一票:D 如果基属性未设置为“虚拟”,除了使用new(带有你提到的缺点)之外,您没有办法覆盖它。但也许您可以以另一种方式达到目标。您尝试覆盖哪个属性?此外,您可以将控件包装在自定义控件中,并按照您的意愿设置属性。 - Kevin Gosse
UIElement是一个库类,所以请只命名SomeProperty。然后有人可以查找规格。答案:这取决于情况。 - H H
@所有人:我无法控制我提到的基类..所以我能做的就是玩我的MyUserControl类。 - Ajai
可能是WPF在XAML中使用继承类的override属性的重复问题。 - H H
显示剩余6条评论
2个回答

20

如果我理解正确的话,以下内容是否可行:

public class BaseClass
{
    public int MyProperty
    {
       get; set;
    }
}
public class ChildClass : BaseClass
{
    public new int MyProperty
    {
       get
       {
           return base.MyProperty;
       }
       set
       {
           if(DoYourCheckingStuff(value))
           {
               base.MyProperty = value;
           }
       }
    }
}

我没有测试过这个方法。

虽然这种方式似乎很hack,你实际上想要对哪个属性进行“控制”?因为可能有更简单的方法来完成这个任务。

例如:更改UserControl使其宽度不能在100到200之间设置(虽然这可能是一种相当糟糕的方法),通过隐藏它的Width属性:

public class MyUserControl : UserControl
{
    public new double Width
    {
        get
        {
            return base.Width;
        }
        set
        {
             if(!(value > 100 && value < 200))
                 base.Width = value;
        }
    }
}

我无法控制基类。我只能在MyUserControl类中进行更改。 - Ajai
1
很遗憾,这对于依赖属性来说完全没有意义。 - H H
3
请注意,如果用户使用基类更改属性,您将不会收到通知:((UIElement)yourControl).IsHitTestVisible = false; - Kevin Gosse
2
哇,那是不可取的;这是一个糟糕的hack。解决方案应该是不要将您的属性命名为基类中的属性名称 - user1228
1
@Will:我同意你的看法。这可能不是设计控件的最佳决策。但是我故意需要重写它,因为我不是设计基类的人,并且在设置特定属性之前需要检查一些条件。 - Ajai
显示剩余4条评论

-2

你可以像重写方法一样重写属性。

public new int Age()
{
    get
    {
        return Age ?? 21;
    }
    set
    {
        Age = value;
    }
}

3
也就是说,如果基础方法是虚拟的或抽象的。 - Kevin Gosse
1
你应该使用 "new" 而不是 "override"。"override" 用于 "virtual" 属性。 - mircea
1
使用 new 关键字并不是 覆盖 成员,而是 隐藏 成员 - 这是很大的区别。正如 @Will 在上面的评论中所述...“这是不可取的”。 - IAbstract
1
常见问题包括: 1)基本函数仍将访问基本属性。 2)BaseClass thing = new ChildClass(); thing.Age = 2; // 这作用于 BaseClass.Age 而不是 ChildClass.Age。 - Chris McCowan

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