WPF: Using Viewbox and Canvas to create a virtual resolution workspace

image First, for you SilverLight 2.0 junkies, you can skip over this.  SilverLight 2.0 doesn't (yet?) support the WPF ViewBox.

The problem: when you start working with WPF you notice pretty quickly WPF likes to handle the rendered size of UI elements.  This is good, until you realize that WPF uses DPI and not screen pixels for units of measurement and you need to map pixels to WPF.  Since you may be new to DPI, here is the short version:

DPI stands for "dots per inch" and default for Windows and WPF is 96 DPI.  To calculate pixels from DPI you take the source width, divide by source DPI, and multiple by target DPI.  So, if you set a width of 100 in WPF (96 DPI) on a default Windows screen you have 100 / 96 * 96 = 100 pixels.  If the user has set their system to 120 DPI aka "Large Fonts", you have 100 / 96 * 120 = 125 pixels.

Why the virtual insanity?  Well, the user that set 120 DPI is asking to make the UI easier to read by making it bigger - but they are still running their monitor at the same pixel resolution.  It's also conceivable that some anal retentive user set their DPI to 87.5 because they measured the number of pixels in an inch with a ruler held up to the monitor.  We are programmers, not psychologists, so we shouldn't question this and honor the setting.

Enough theory, what happens when you have a set resolution like 720x480 pixels (common digital video) and want to be able to place elements in that space, without resorting to the (numerous) WPF size methods and your pathetic calculus skills?  Enter the XAML below:

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    Title="VirtualInsanity" Height="200" Width="300">
    <Viewbox>
        <Canvas Height="480" Width="720" Background="Gray" Margin="10">
            <Ellipse Height="300" Width="500" Fill="Yellow" 
                     Canvas.Top="100" Canvas.Left="100" />
        </Canvas>
    </Viewbox>
</Window>

image This XAML produces the image shown on the left - the interesting stuff is the Height and Width properties.  The Window is 300x200 (all units DPI), but the Canvas is 720x480 - the magic is the Viewbox control, which expands a control to fill the available space (while keeping the aspect ratio) but the control can assume absolute size.  The Ellipse placed in the Canvas is place and sized assuming 720x480.  If you run this XAML you'll see that you can resize the widow and everything grows or shrinks with the size change.

If you looking to understand more of this type of WPF magic, I can't recommend a book more than Applications = Code + Markup by Charles Petzold.

Posted By Mike On Friday, March 21, 2008
Filed under wpf viewbox canvas | Comments (2)

Submit this story to DotNetKicks   

Timothy Khouri - Tuesday, March 31, 2009 8:07:22 AM

Very well explained and well done :)... I realize this is an older post, but I just came across the Viewbox for the first time and googled it.

Ben - Friday, February 12, 2010 11:27:59 AM

Well, I'll have to argue with you about your perspective on DPI. It's a calibration figure for your screen, not something to 'zoom' or make fonts bigger. It makes 1 inch on the screen equal to 1 inch in real life. If your screen's native DPI is 144 (for example, my wonderful 1440x1050 12" laptop screen), you should set your system's DPI to 144. If your screen's DPI is 96, then leave it at 96. Having it set below your screen's native DPI results in everything being "tiny" (or what some people mistakenly think of as "screen real estate"); the opposite makes things too large. I'll go out on a limb and say that incorrectly setting your DPI is wrong.

One of the beauties of WPF and the new graphics model introduced in vista is that programmers can now program resolution independent guis without having to work for it. Programmers/designers need to quit thinking about their guis in terms of pixels and start thinking about them in terms of *inches*. A unit of WPF is not "1 pixel"; it's "1/96th of an inch".

However, this means programmers have to remember that not everyone has a huge screen. I've seen numerous programs (even Visual Studio 2010 beta!!) that assign some arbitrary size to windows that makes an assumption based on screen resolution, not screen size. This causes the windows to extend beyond the edge of the screen. Needless to say, it's pure crap. An assumption of a minimum size of 10 inch screens (remember, that's 10inches diagonally--8.5 horizontal and 5 vertical) may be reasonable. That means the maximum you can set your window's default starting dimensions to is 800x480 (but it should be a little smaller yet, because the taskbar takes up a portion of that--and not everyone has their taskbar at the bottom or top!!). Of course, if you wanted to get fancy, you determine your window size at start up from reading the system's screen dimensions.

So, lets be good programmers.

Leave a comment



Your name:
 

Your email (not shown):
 
Will display your Gravatar image.

Your website (optional):



About Michael

Michael C. Neel, born 1976 in Houston, TX and now live in Knoxvile, TN. Software developer, currently .Net focused. Board member of ETNUG and organizes CodeStock, East Tennessee's annual developers conference. .Net speaker, a Microsoft ASP.NET MVP and ASPInsider. Co-Founder of FuncWorks, LLC and GameMarx.

Proud father of two amazing girls, Rachel and Hannah, and loving husband to Cicelie who inflates and pops his ego as necessary.

 Subscribe to ViNull.com |  Comments

Follow me on Twitter | Contact Me

Related Posts

Ada Lovelace Day: Mary Everest Boole and Beautiful Math

October 16th, 2012 is technically Ada Lovelace Day, a day for celebrating women in science, technology, engineering, and math (STEM), but as long as it's ... Read more

SilverLight 2.0: Setting the Background of a Button

I know, this hardly seems a topic worthy of a blog post.  To create a Button in SilverLight like the first in the picture is just: <Button Content="Stock ... Read more

Code Camp Room Planner

I just finished creating a project on CodePlex for the Code Camp Room Planner, a little app I wrote to help me plan the schedule at CodeStock 2009.  ... Read more

WPF: Threading basics in WPF

In my previous WPF post I created a simple photo viewer.  If you run the application, you'll notice things "lock up" while downloading an image.  ... Read more

WPF: Dive into WPF

For this first post on WPF I've decided it would be best to start off with a "real" application.  This means we'll need those thing almost all applications ... Read more

XNA 3D Primer by Michael C. Neel

XNA 3D Primer by Michael C. Neel
Buy Now: [ Amazon ] [ Wrox ]

GameMarx

CodeStock

ASPInsiders Member

ETNUG Member