2

I am just starting WPF and it is frustrating the hell out of me. It seems that many properties are null by default (at least those I am working on at the moment) and hence when it compiles and run, nothing happens.

Is there a quick way or a standard workflow procedure to set default values for WPF objects?

For example, I put a Canvas and a Button in XAML view, and then went to code view to add an event handler on the Button to Canvas.Children.Add(new Ellipse()) and then nothing happens. Then I thought maybe I should specify the Width and Height. Still nothing happens. Finally, after much struggling I found the Shape.Stroke property.

Then there is no intuitive Ellipse.X and Ellipse.Y to position the Ellipse. Again, took an hour to find the Canvas.SetLeft().

The final straw is when I try to do Canvas.SetLeft(Random.Next(0, (int)Canvas.Width)); It give a runtime error because Canvas.Width is NULL?!!? Goodness...

Sure, WPF gives a lot of features, but seems like a lot of work coming from a Winforms Graphics.DrawEllipse() .. *sweat*

Jake
  • 11,273
  • 21
  • 90
  • 147
  • Hello Jake. Remember I told you NOT to manipulate UI elements in code? THIS is why. in this case you should use `ActualWidth` instead of `Width`. – Federico Berasategui Mar 14 '13 at 22:16
  • 1
    Also, I strongly encourage you to use [Snoop](http://snoopwpf.codeplex.com/). This will help you A LOT when dealing with the WPF visual tree (you can inspect the running application, and see what's in the visual tree, and all the properties for everything. – Federico Berasategui Mar 14 '13 at 22:18
  • Another vote for Snoop: it *will* make your life far more enjoyable. – JerKimball Mar 14 '13 at 22:20
  • @Jerkimball I missed the mouse click and I gave the bounty to the other guy. I'm sorry I feel in debt with you.. =( – Federico Berasategui Mar 14 '13 at 22:23
  • `Sure, WPF gives a lot of features, but seems like a lot of work coming from a Winforms Graphics.DrawEllipse() .. *sweat*` - The problem is you're too used to winforms, and all its hacks. WPF requires a completely different mentality (I already told you this as well). Don't try to use WPF in a winforms manner, and you will not have these frustrations. WPF has no frustrations, just simple, simple properties and `INotifyPropertyChanged`... – Federico Berasategui Mar 14 '13 at 22:25
  • `Is there a quick way or a standard workflow procedure to set default values for WPF objects?` - Yes, that's called a [`Style`](http://msdn.microsoft.com/en-us/library/ms745683.aspx). Another thing I would like to mention is that once you `Graphics().Hack()` in winforms, you're condemned to implement a bunch of other `Graphics.Hack()` in order to change a pixel in the first hack-drawn stuff. Whereas WPF gives you the ability to `Retain` these elements for later use or manipulation (which I insist, should NOT be done in code). – Federico Berasategui Mar 14 '13 at 22:38
  • @highcore hah - no worries; one of these days I'll think through a thorough "anti-injector" approach and let you know. :) – JerKimball Mar 14 '13 at 22:51
  • @HighCore The Diagram Designer tutorial http://www.codeproject.com/Articles/22952/WPF-Diagram-Designer-Part-1 uses Canvas.Children.Add to add Path draged onto the Canvas, and not Binding. I am just learn a step at a time. In this case, I happen to visit one that uses code to add UI. – Jake Mar 15 '13 at 19:49
  • @jake you're right, I saw that, and I think it's a flaw. Look at [this example I made](http://stackoverflow.com/questions/15421816/wpf-render-event-not-drawing-anything/15423602#15423602) – Federico Berasategui Mar 15 '13 at 19:59

2 Answers2

2

In WPF if you dont explicitly set the Width/Height in xaml the size will be determined by the Elements layout Container, so to access the Width/Height of an Element like this you use the properties ActualWidth/Actualheight, these return the Rendered size of the Element

Example:

Canvas.SetLeft(Random.Next(0, (int)Canvas.ActualWidth));

If you want to create Default values for a Element you can create a style in xaml for that Element

Example:

<Style TargetType="Ellipse">
    <Setter Property="Stroke" Value="Black"/>
</Style>
sa_ddam213
  • 42,848
  • 7
  • 101
  • 110
  • What happened in my case was I dragged and drop the Cavas from the toolbox onto the form area and Visual Studio automatically set the margin for me, but I am shocked that the Width is not automatically derived and is still NULL. But using style makes sense... although it feels like a lot of overhead just to get simple hello world working. – Jake Mar 15 '13 at 19:57
1

WPF does have a rough learning curve. One of the tougher things is to dispense somewhat with the techniques you may be used to and embrace the WPF-approach. Xaml is the way to go for defining controls and their properties - Xaml is a language whose only real purpose to do declaration well. In essence, think of the Xaml portion of your code as a glorified constructor.

<Window x:Class="TestWpfApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        x:Name="Window"
        Title="MainWindow"
        Width="640"
        Height="480">       
    <Canvas>
        <Ellipse Canvas.Left="50"
                 Canvas.Top="50"
                 Width="142"
                 Height="88"
                 Fill="Black" />
    </Canvas>
</Window>

The declaration above takes advantage of Xaml's nifty syntax for Attached Properties.

You might want to investigate Styles if you find yourself setting a set of common properties on like objects often.

cunningdave
  • 1,470
  • 10
  • 13
  • Perhaps because I am still a noob, but I don't understnd how putting the ellipsed in during designtime is useful at all. I understand that the ellipsed can be a template and the Left, Top, Width, Height and Fill properties can come from a binding. But that seems very restrictive given that not all my UIElements may adhere to a single template. – Jake Mar 15 '13 at 19:54
  • I'm just trying to answer your question. You asked what is the standard approach to set default values for your controls, and this is it. If you need dynamic behaviour for the position of the ellipse, then that's a different question. These are not design-time settings, btw, this is code that runs in your Window (or UserControl) constructor. That's what InitializeControl() does. – cunningdave Mar 18 '13 at 15:16