Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I programmatically position a canvas in Silverlight?

I'm using Silverlight 3/C#, and I'm trying to create some XAML objects programatically in response to a user clicking on a button.

However, I can't seem to position a Canvas object that I have created - when I call SetValue() on the new Canvas with the Canvas.LeftProperty value, the browser window clears to an empty screen.

I have a simple function that exhibits the problem (I started out with something more complex):

    private Canvas MakeNewCanvas()
    {
        Canvas newCanvas = new Canvas();
        newCanvas.Width = newCanvas.Height = 50;
        newCanvas.SetValue(Canvas.LeftProperty, 10);
        return newCanvas;
    }

and a simple button click handler that calls this:

    private void MyButton_Click(object sender, System.Windows.RoutedEventArgs e)
    {
        myPage.Children.Add(MakeNewCanvas());
    }

NB: myPage is a Canvas object defined in my app's MainPage XAML file.

I've traced this through in the VS debugger with the SL app executing in Firefox, and whenever it executes the SetValue() line, the browser goes white and starts trying to download data (according to the status bar). I tried calling SetValue() after I've put the Canvas in the XAML tree with something like:

    myPage.Children.Add(newCanvas);
    newCanvas.SetValue(Canvas.LeftProperty, 10);

but it makes no difference - as soon as the SetValue() call is hit, the browser goes white.

The Canvas class seems to have no direct method of setting Left/Top on itself, apart from the SetValue() function with dependency property enum values. There's also Canvas.SetLeft() and Canvas.SetTop() but I guess they're just shims onto SetValue(). Using them didn't help anyway.

If I don't call SetValue(), then my canvas appears (and child objects I've added to it) in the SL app as you might expect, in the very top left.

If I create and position a Canvas object in Expression Blend, then the XAML generated includes Canvas.Left and Canvas.Top property values on the Canvas itself, as I would expect, so it seems to me that what I'm trying in C# should work.

But I don't seem to be able to set the left/top values myself from C# without the SL in the browser going all weird.

Any ideas?

Edit: my approach is correct, but canvas coords need to be floating point, not integer - see accepted answer for details.

like image 605
Slacker Avatar asked Nov 08 '09 16:11

Slacker


1 Answers

Trying your code, but with the debugger catching exceptions, I get:

DependencyProperty of type System.Double cannot be set on an object of type System.Int32.

which is a really stupid gotcha - SetValue only takes Object, so you're prone to a problem like this.

Try either:

newCanvas.SetValue(Canvas.LeftProperty, 10.0);

or

Canvas.SetLeft(newCanvas, 10);

and it will probably work.

like image 54
Jim Lynn Avatar answered Sep 24 '22 11:09

Jim Lynn