#682 – Panel Elements Only Fire Mouse Events When Background Is Set

If you create an element derived from Panel, like Canvas, and wire up any of the mouse-related events, you’ll notice that you don’t see your events unless you’ve set the Background property of the Panel.  You will, however, see the routed events when a child element of the canvas originates the event.

In the example below, we don’t see MouseMove event on the Canvas unless we’re moving the mouse over one of the child Buttons.

    <Canvas MouseMove="Canvas_MouseMove">
        <Button Content="Preston Sturges" MouseMove="Button_MouseMove"
                Canvas.Left="10" Canvas.Top="10"/>
        <Button Content="John Ford" MouseMove="Button_MouseMove"
                Canvas.Left="10" Canvas.Bottom="10"/>
        <Button Content="Michael Curtiz" MouseMove="Button_MouseMove"
                Canvas.Right="10" Canvas.Top="10"/>
    </Canvas>

If you do want to see mouse events on a Panel, you need to explicitly set its Background property.  If you don’t want a background color, you can just set the property to Transparent.

    <Canvas MouseMove="Canvas_MouseMove" Background="Transparent">

Advertisements

#537 – Changing a Layout Panel to a Different Type

In Blend, you can easily change an existing layout panel to a different type of panel, by interacting with the panel object in the Objects and Timeline panel.

Let’s say that you have a series of Button controls as child elements of a StackPanel.

If you want to use a UniformGrid panel as a container, rather than the StackPanel, you can right-click on the StackPanel object in the Objects and Timeline panel and select Change Layout Type.  Then select the desired type of panel that you’d like to use.

Once you select the new layout panel type, the XAML will be updated to replace the old panel with the new one.  Both the artboard and the Objects and Timeline panel will also immediately update to reflect the new panel.

#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>

#329 – Principles of Layout in WPF

WPF uses a flow-based layout model by default, where child elements are placed in a container and explicitly positioned based on their content.  This is as opposed to coordinate-based layout, where controls are given specific sizes and positions.

Parent containers (deriving from Panel) are responsible for figuring out both the size and position of all of their child controls.

In general, we following the following layout principles in WPF:

  • Don’t give controls a specific size, but let them size to fit their content
  • Don’t give controls a specific location, but let the parent container position them
  • Layout containers can be nested inside of other layout containers

#180 – How Layout Works

Layout in WPF is the process by which a container (e.g. Grid, StackPanel) arranges its child elements (e.g. Button, Label).  The container figures out the final size and position of each child element, which dictates how the container’s children will be rendered.

The layout process is triggered when a container is first being rendered or when a property on a child control changes (if that property can affect layout).

Layout is basically a conversation between the container and its children.  This conversation consists of two phases:

  • Measure – Container asks each child what its desired size is
  • Arrange – Container figures out how to arrange its children and decides on final position and size of each child

How a container arranges its children is dependent on the specific class.  E.g. A Grid puts its children in rows and columns, while a StackPanel stacks children horizontally or vertically.