Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I create an adaptive layout in WPF?

Tags:

c#

.net

layout

wpf

A website can be designed to adapt to smaller screen sizes using media queries. For example, three columns on a wide screen, one column on a low-resolution phone.

Is there a similar technique for WPF to adjust the layout based on available screen space or parent control size?

For example, I'd like to have 3 columns displayed horizontally on a large screen, but displayed vertically on smaller screen. Ideally, I'd like to formulate layouts like this: "If this control's width is less than 400 points, rearrange these controls in that way."

How can I create an adaptive design like this in WPF? That is, define different layouts for controls for specific parent control sizes?

Ideally controls should be rearranged instead of duplicated or recreated, to avoid being extremely slow.

like image 861
Athari Avatar asked Dec 23 '12 19:12

Athari


Video Answer


1 Answers

The easiest way to do this is with DataTriggers and a Converter to test if the bound value is greater or less than a parameter.

This will allow you to easily adjust the style setters based on a bound value. For example, you could use

<Style x:Key="MyControlStyle">
    <!-- Default Values -->
    <Setter Property="Grid.Row" Value="0" />
    <Setter Property="Grid.Column" Value="0" />
    <Style.Triggers>
        <DataTrigger Value="True" 
                     Binding="{Binding ActualHeight, ElementName=MyWindow, 
                         Converter={StaticResource IsValueLessThanParameter}, 
                         ConverterParameter=400}">
            <!-- Values to use when Trigger condition is met -->
            <Setter Property="Grid.Row" Value="1" />
            <Setter Property="Grid.Column" Value="1" />
        </DataTrigger>
    </Style.Triggers>
</Style>

In the case where you have a more complex layout with many pieces that change based on some triggered value, you can replace entire Templates with your trigger instead of just individual properties

<Style x:Key="MyContentControlStyle" TargetType="{x:Type ContentControl}">
    <Setter Property="ContentTemplate" Value="{StaticResource BigTemplate}" />
    <Style.Triggers>
        <DataTrigger Value="True" 
                     Binding="{Binding ActualHeight, ElementName=MyWindow, 
                         Converter={StaticResource IsValueLessThanParameter}, 
                         ConverterParameter=400}">
            <Setter Property="ContentTemplate" Value="{StaticResource LittleTemplate}" />
        </DataTrigger>
    </Style.Triggers>
</Style>

I believe you can also bind to the SystemParameters object to use additional information about the application in your bindings, although I can't remember the exact syntax for it right now.

like image 182
Rachel Avatar answered Sep 19 '22 04:09

Rachel