#391 – Anti-Aliasing Can Lead to Fuzzy GUI Elements

You specify positions and sizes for GUI elements in WPF using device-independent units.  A unit is 1/96 of an inch, or 1 pixel on a 96 dpi display.  This allows the object to have a consistent physical size, regardless of the output resolution.

Because you’re not specifying things in terms of pixels, object edges don’t always line up exactly with pixels.  WPF uses anti-aliasing when rendering GUI elements.  For example, if an element only covers half of a pixel, that pixel is rendered at half intensity.

This can lead to fuzzy edges of GUI elements and looks especially bad for elements designed to be very small.

Below is an example of a ListBox containing items that include a couple of vertical lines (specified using a Border element).  The lines are all 1 display unit wide.  Some are 1 pixel wide, but many of them look fuzzy.

I’ll talk next time about how to fix this.

#390 – Scrollbar Visibility in a ScrollViewer

The HorizontalScrollbarVisibility and VerticalScrollbarVisibility properties dictate which scrollbars appear in a ScrollViewer.  The properties can be set to one of the ScrollBarVisibility values:

  • Disabled – scrollbar doesn’t appear and user can’t scroll any of the contained content

  • Hidden – scrollbar doesn’t appear, but the user can still scroll the content, e.g. with arrow keys

  • Visible – scrollbar always visible, but greyed out if there is nothing to scroll

  • Auto – Scrollbar appears only when needed

#389 – Wrap a Panel in A ScrollViewer to Provide Scrolling Support

The layout containers in WPF do not automatically provide scrolling support.  To scroll the content in a container, however, you can wrap it in a ScrollViewer control.

    <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
        <StackPanel Orientation="Vertical" >
            <Label Content="I am happy to join with you today in what will go down in history as the greatest demonstration for freedom in the history of our nation." />
            <Label Content="Some famous speeches:"/>
            <Label Content="I Have a Dream. --MLK" />
            <Label Content="Inaugural Address --JFK"/>
            <Label Content="First Inaugural --FDR"/>
            <Label Content="Pearl Harbor Address --FDR"/>
            <Label Content="1976 DNC Keynote --Barbara Jordan"/>
        </StackPanel>
    </ScrollViewer>



Notice that we’ve set the visibility of both scrollbars to Auto. By default, though, the horizontal scrollbar is disabled and the vertical scrollbar is visible.

You can set the HorizontalScrollbarVisibility and VerticalScrollbarVisibility properties to one of the following: Disabled, Visible, Auto or Hidden.

#388 – Layout Containers Don’t Provide Scrolling Support

None of the WPF panel controls (containers) automatically provide scrollbars.  If their child controls do not fit in the available space, the child controls are clipped.

In the example below, we have a vertical StackPanel with a series of Label controls.  Notice that the first label doesn’t fit the width of the window and is clipped on the right.  The last label also does not fit and is clipped at the bottom of the window.

#387 – Set Background Color to See How Layout Works

It’s sometimes hard to understand how a container is laying out its children.  You can use the Background property of each control, or of the panels, to get a better idea of where things are.

Suppose that we have a GUI that includes a handful of controls and two nested panels.

    <StackPanel Orientation="Vertical">
        <Label Content="Bob's Your Uncle" HorizontalAlignment="Right"/>
        <StackPanel Orientation="Horizontal">
            <Label Content="Paul"/>
            <Button Content="Ringo" Margin="10"/>
            <TextBox Text="George" VerticalContentAlignment="Bottom"/>
        </StackPanel>
        <TextBox Text="Herman was here.."/>
    </StackPanel>

The GUI would look like this:

To better see how things are being layed out, we can set the Background to a different color for each element.

    <StackPanel Orientation="Vertical" Background="Pink">

        <Label Content="Bob's Your Uncle" HorizontalAlignment="Right" Background="Lavender"/>

        <StackPanel Orientation="Horizontal" Background="LightBlue">
            <Label Content="Paul" Background="Red"/>
            <Button Content="Ringo" Margin="10" Background="Green"/>
            <TextBox Text="George" VerticalContentAlignment="Bottom" Background="Blue"/>
        </StackPanel>

        <TextBox Text="Herman was here.." Background="Orange"/>
    </StackPanel>

#386 – Layout = Panels + FrameworkElements + Alignment/Margins/Padding

Layout in WPF is the process by which the location and size of all user interface elements is determined.

A user interface is composed of an outer Window or Page which contains a hierarchy of user interface elements.  The hierarchy can contain individual user interface elements or Panels, which in turn contain a collection of child FrameworkElements.

Panel is an abstract class that serves as a parent for specific layout panels, including Canvas, DockPanel, Grid, StackPanel and WrapPanel.

A panel will contain a collection of child FrameworkElement instances.  These can be individual controls that derive from FrameworkElement, directly or indirectly.  Because Panel is itself a child of the FrameworkElement class, a panel can contain other panels.

FrameworkElement child elements are position within a parent using properties related to alignment, margins and paddingThese properties include:

  • HorizontalAlignment, VerticalAlignment  and Margin  (from FrameworkElement)
  • HorizontalContentAlignment, VerticalContentAlignment and Padding  (from Control)

#385 – You Can Nest Panel Controls

An application is typically composed of a top-level panel control that contains other panels, creating a hierarchy of panels that defines the layout of your GUI.

Here’s an example, with the top-level container being a three-row Grid that contains a StackPanel in the 1st row, a 2×2 Grid in the 2nd row, and another StackPanel in the 3rd row.

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="30"/>
            <RowDefinition/>
            <RowDefinition Height="30"/>
        </Grid.RowDefinitions>

        <StackPanel Grid.Row="0" Orientation="Horizontal" HorizontalAlignment="Right">
            <Label Content="Enter your name:"/>
            <TextBox Width="150"/>
        </StackPanel>

        <!-- 2x2 grid for main app content -->
        <Grid Grid.Row="1" >
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>
            <Button Content="Something here" Grid.Row="0" Grid.Column="0"/>
            <Label Content="Other stuff here" Grid.Row="1" Grid.Column="1"/>
        </Grid>

        <StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Center">
            <Button Content="OK" Margin="10,5"/>
            <Button Content="Cancel" Margin="10,5"/>
        </StackPanel>
    </Grid>