Silverlight Canvas: How does it work?
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?!
精彩评论