开发者

Silverlight Canvas: How does it work?

开发者 https://www.devze.com 2022-12-14 06:27 出处:网络
In silverlight Canvas class (with Reflector) has very simple implementation: 3 attached dependency properties (Left, Top, ZIndex) and 2 ovverides of MeasureOverride and ArrangeOverride methods which d

In silverlight Canvas class (with Reflector) has very simple implementation: 3 attached dependency properties (Left, Top, ZIndex) and 2 ovverides of MeasureOverride and ArrangeOverride methods which do nothing special.

But if i use my implementation like:

class MyCanvas : Panel { /* Top and Left dependency properties implementation */ }

And then use MyCanvas in XAML like standard Canvas. That's not working as expected (i see the empty screen).

How Canvas was implemented?

-- Additional code: MyCanvas.cs

public class MyCanvas : Panel
{
    public static double GetTop(DependencyObject obj)
    {
        return (double)obj.GetValue(TopProperty);
    }

    public static void SetTop(DependencyObject obj, double value)
    {
        obj.SetValue(TopProperty, value);
    }

    // Using a DependencyProperty as the backing store for Top.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty TopProperty =
        DependencyProperty.RegisterAttached("Top", typeof(double), typeof(MyCanvas), new PropertyMetadata(0.0));


    public static double GetLeft(DependencyObject obj)
    {
        return (double)obj.GetValue(LeftProperty);
    }

    public static void SetLeft(DependencyObject obj, double value)
    {
        obj.SetValue(LeftProperty, value);
    }

    // Using a DependencyProperty as the backing store for Left.  This enables animation, 开发者_如何学运维styling, binding, etc...
    public static readonly DependencyProperty LeftProperty =
        DependencyProperty.RegisterAttached("Left", typeof(double), typeof(MyCanvas), new PropertyMetadata(0.0));
}

Used in XAML like:

<local:MyCanvas>
    <Rectangle 
        local:MyCanvas.Left="10"
        local:MyCanvas.Top="10"
        Width="100"
        Height="100"
        Fill="Black" />
</local:MyCanvas>

if change MyCanvas to standard Canvas, i can view black-filled rectangle at position 10,10.

<Canvas>
    <Rectangle 
        Canvas.Left="10"
        Canvas.Top="10"
        Width="100"
        Height="100"
        Fill="Black" />
</Canvas>


This seems to be a bug in the Silverlight disassembling engine of Reflector. You can build your own Silverlight Canvas control with the following steps:

  • Disassemble the WPF canvas control in Reflector and copy the code to Visual Studio.
  • Remove the DependencyProperties Bottom and Right, as well as their Get and Set methods.
  • Remove the Bottom and Right clauses from ArrangeOverride.
  • Replace FrameworkPropertyMetadata by PropertyMetadata.
  • Remove the property validation arguments from the DependencyProperty initialization.

Be aware that the Canvas created this way does not have a ZIndex property.


Canvas is nothing more than a Panel with Left and Top attached properties, as you said. According to MSDN:

Defines an area within which you can explicitly position child objects by using coordinates that are relative to the area.

That's it- a Canvas can have an explicit location inside another FrameworkElement-derived container. If you're not seeing your handrolled Canvas, you may have a rendering error. Have you tried changing the background color to make sure you can see it?


I can implement MeasureOverride and ArrangeOvverride something like:

    protected override Size MeasureOverride(Size availableSize)
    {
        foreach (var element in Children)
            element.Measure(availableSize);
        return base.MeasureOverride(availableSize);
    }

    protected override Size ArrangeOverride(Size finalSize)
    {
        foreach (var element in Children)
        {
            var left = GetLeft(element);
            var top = GetTop(element);
            var size = element.DesiredSize;
            element.Arrange(
                new Rect(left, top, size.Width, size.Height)
                );
        }
        return base.ArrangeOverride(finalSize);
    }

And i can view black rectangle as expected in my example of MyCanvas usage.

But Canvas not implement these methods. How does it work?!

0

精彩评论

暂无评论...
验证码 换一张
取 消