rPulvi
rPulvi

Reputation: 946

WPF - Encapsulate custom Canvas in ScrollViewer

I need to have a Custom Panel that acts as a Canvas but really is a ScrollViewer with a Canvas inside. The user should be able to add controls like in a canvas; I need the ScrollViewer wrapper to handle zoom and pan behaviours.

So, I started writing the control:

[ContentProperty("Children")]
public class MyContainer : ScrollViewer, IAddChild
{
    private Canvas _innerCanvas;

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public UIElementCollection Children
    {
        get { return _innerCanvas.Children; }
    }

    public MyContainer()
    {
        this._innerCanvas = new Canvas();
        this.Content = _innerCanvas;

        _innerCanvas.Height = this.ActualHeight;
        _innerCanvas.Width = this.ActualWidth;
    }

    void IAddChild.AddChild(object value)
    {
        _innerCanvas.Children.Add(value as UIElement);
    }

    void IAddChild.AddText(string text)
    {
        ;
    }
}

but it doesn't work. If I try to use it in XAML

<Controls:MyContainer>
    <TextBlock Height="92" Canvas.Left="324" TextWrapping="Wrap" Text="TextBlock 1" Canvas.Top="267" Width="284"/>
    <TextBlock Height="92" Canvas.Left="462" TextWrapping="Wrap" Text="TextBlock 1" Canvas.Top="267" Width="284"/>
</Controls:MyContainer>

the children aren't visible.

What is wrong?

Upvotes: 2

Views: 294

Answers (1)

CKII
CKII

Reputation: 1486

You set the size of your canvas to ActualWidth and ActualHeight at the Ctor, but they are not yet initialized at that point. ActualWidth and ActualHeight are only meaningful when the control is presented on the screen. Try to subscribe to the Loaded event of the ScrollViewer, and change the Canvas size then:

public MyContainer()
{
    this._innerCanvas = new Canvas();
    this.Content = _innerCanvas;

    this.Loaded += ScrollViewer_Loaded;
}

public void ScrollViewer_Loaded(object sender, EventArgs e)
{
    _innerCanvas.Height = this.ActualHeight;
    _innerCanvas.Width = this.ActualWidth;
} 

Upvotes: 2

Related Questions