最近在读《WPF程序设计指南》。关于Dependency Property这部分是一知半解。我的问题是:
父窗口,或者是Element Tree顶端的窗口,如何去让Child Element去继承自己的Dependency Property?
父窗口特别是Panel是透过维持一个Collection来记录Child Element对应的Dependency Property吗?Dependency Property是通过怎样的一种机制实现Inheirit的?
真的是不解啊。麻烦高手告知,谢谢。分数不够可以加,关键是要说到点上。我不想只知道How,我更想知道Why。

解决方案 »

  1.   


    按你描述的意思  
    你是要让window里的button继承window的属性? 你可知道什么是继承
      

  2.   


    //--------------------------------------------
    // CanvasClone.cs (c) 2006 by Charles Petzold
    //--------------------------------------------
    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Media;namespace Petzold.PaintOnCanvasClone
    {
        public class CanvasClone : Panel
        {
            // Define two dependency properties.
            public static readonly DependencyProperty LeftProps;
            public static readonly DependencyProperty TopProps;        static CanvasClone()
            {
                // Register the dependency properties as attached properties.
                //  Default value is 0 and any change invalidates parent's arrange.
                LeftProps = DependencyProperty.RegisterAttached("LeftProp",
                        typeof(double), typeof(CanvasClone),
                        new FrameworkPropertyMetadata(0.0, 
                            FrameworkPropertyMetadataOptions.AffectsParentArrange));            TopProps = DependencyProperty.RegisterAttached("TopProp",
                        typeof(double), typeof(CanvasClone), 
                        new FrameworkPropertyMetadata(0.0, 
                            FrameworkPropertyMetadataOptions.AffectsParentArrange));
            }
            // Static methods to set and get attached properties.
            public static void SetLeft(DependencyObject obj, double value)
            {
                obj.SetValue(LeftProps, value);
            }
            public static double GetLeft(DependencyObject obj)
            {
                return (double)obj.GetValue(LeftProps);
            }
            public static void SetTop(DependencyObject obj, double value)
            {
                obj.SetValue(TopProps, value);
            }
            public static double GetTop(DependencyObject obj)
            {
                return (double)obj.GetValue(TopProps);
            }
            // Override of MeasureOverride just calls Measure on children.
            protected override Size MeasureOverride(Size sizeAvailable)
            {
                foreach (UIElement child in InternalChildren)
                    child.Measure(new Size(Double.PositiveInfinity, 
                                           Double.PositiveInfinity));            // Return default value (0, 0).
                return base.MeasureOverride(sizeAvailable);
            }
            // Override of ArrangeOverride positions children.
            protected override Size ArrangeOverride(Size sizeFinal)
            {
                foreach (UIElement child in InternalChildren)
                    child.Arrange(new Rect(
                        new Point(GetLeft(child), GetTop(child)), child.DesiredSize));            return sizeFinal;
            }
        }
    }//---------------------------------------------------
    // PaintOnCanvasClone.cs (c) 2006 by Charles Petzold
    //---------------------------------------------------
    using System;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Shapes;namespace Petzold.PaintOnCanvasClone
    {
        public class PaintOnCanvasClone : Window
        {
            [STAThread]
            public static void Main()
            {
                Application app = new Application();
                app.Run(new PaintOnCanvasClone());
            }
            public PaintOnCanvasClone()
            {
                Title = "Paint on Canvas Clone";            CanvasClone canv = new CanvasClone();
                Content = canv;            SolidColorBrush[] brushes = 
                    { Brushes.Red, Brushes.Green, Brushes.Blue };            for (int i = 0; i < brushes.Length; i++)
                {
                    Rectangle rect = new Rectangle();
                    rect.Fill = brushes[i];
                    rect.Width = 200;
                    rect.Height = 200;
                    canv.Children.Add(rect);
                    CanvasClone.SetLeft(rect, 100 * (i + 1));
                    CanvasClone.SetTop(rect, 100 * (i + 1));
                }
            }
        }
    }Code 如上所示。我的问题是,CanvasClone如何让rect对象保持下来Top,Left等属性。
    CanvasClone的Static方法SetLeft,调用Obj.SetValue(LeftProps, value)是怎样影响到rect对象的Left属性?这个程序可以正常的去Set 3个Retangle的Left,Top属性。我的困扰是:
    LeftProps,TopProps只是CanvasClone的属性,它又是如何影响这个Pannel上的3个Rectangle?
      

  3.   

    不好意思,我的表达可能不是很清楚。
    C#初学者,确实相关概念可能不清楚。但是,书上的确是这样写的。Dependency Property可以被继承(沿袭)。
      

  4.   

    看了下你2楼的代码  你这样写肯定是通不过的
    首先public static readonly DependencyProperty LeftProps;
    LeftProps = DependencyProperty.RegisterAttached("LeftProp",
                        typeof(double), typeof(CanvasClone),
                        new FrameworkPropertyMetadata(0.0, 
                            FrameworkPropertyMetadataOptions.AffectsParentArrange));
    命名上面是强制的
    如果你要把这个注册成"LeftProp"  
    那定义就应该是public static readonly DependencyProperty LeftPropProperty;其次具有这个属性的类型是 typeof(CanvasClone)
     public static double GetLeft(DependencyObject obj)
            {
                return (double)obj.GetValue(LeftProps);
            }
    这样写在调用的时候一定会报错  说 obj没有LeftProps属性  
    或者是getvalue返回null而不能强制转成double
      

  5.   

    不好意思,我不仅编译过了。而且运行都正确。
    我真的迷惑了,我以为是透过类型名反射得到Property Value。但是不是你说的那样。5楼的,真的我很想搞清楚这个问题。你把我的代码复制到VS2008,可以运行的。
      

  6.   

    那还真奇怪了
    LeftProps = DependencyProperty.RegisterAttached("LeftProp",
                        typeof(double), typeof(CanvasClone),
                        new FrameworkPropertyMetadata(0.0,
                            FrameworkPropertyMetadataOptions.AffectsParentArrange)); 
    意思是说  只有CanvasClone类型的对象才有这个属性  这个属性类型是double
      

  7.   

    恩是的。原本的代码,这里是Left,LeftProps是我自己改的。
    我就想搞清楚,到底他是如何做到。我以为Rectangle和CanvasClone具有相同属性Left,但WPF似乎好像不是通过这样子实现的。而且,不同类中的Property,即使同名,也不应该就是一个Property。所以WPF肯定是用了别的方法,但是我不知道。
      

  8.   

    Dependency Property真是颠覆了传统的属性的观念。
      

  9.   

    总算搞清楚了。说明如下:1,DependencyObject的SetValue(DependencyProperty dp, object value),如果没有此DependencyProperty,首先会将dp和value放置于一个容器中。不过我没有在DependencyObject的定义中找到是一个什么类型的容器。我感觉应该是一个HashMap这样的东西。 若有这个Property,就会去设置此Property的Value。
    2, DependencyObject透过GetValue(DependencyProperty dp)去获取指定的DependencyProperty的值。若找不到,抛出异常。3,实际上不管上述CanvasClone中的DependencyProperty定义为什么名字,只要Rectangle对象调用了SetValue,rect就会将此Property添加到自己对象上。因为Rectangle也继承自DependencyObject。4,Canvas的ArrangeOverride中调用了Rectangle的GetValue()得到刚刚SetValue进去的DependencyProperty的值,并调用Rectangle的Arrange方法,让Rectangle重新排列。因此看上去,UI上Rectangle的Top,Left属性似乎被影响到了。5,这个DependencyProperty会影响到Parent的Arrange重新排列,因为在Register属性的时候使用到了:FrameworkPropertyMetadataOptions.AffectsParentArrange来初始化FrameworkPropertyMetadata。
    而Arrange又会导致MeasureOverride,MeasuareOverride会导致OnReander重绘。分享给大家,希望能对大家有用。PS:谢谢楼上几位的热情回复。
      

  10.   

    在命名上,最后是不是改成了LeftPropProperty了?