4

I have a UserControl that is made of two grids.

There are two columns in the grid side by side and this grid has the horizontal layout. Column 0 has one data and Column 1 has another data.

I need to have this control to be able to change the layout from horizontal to vertical depending on the screen this control should be displayed in, so instead of having Columns 0 and 1 displaying the data, the Row 0 and Row 1 should now display the data.

What is the best way to accomplish this?

Thank you

2 Answers2

3

Try to use StackPanel and change property Orientation from Horizontal to Vertical.

ajacian81
  • 7,419
  • 9
  • 51
  • 64
1

You can use ControlTemplates and DataTriggers to choose this, if you want more control than a StackPanel can give you. Here's a quick-n-dirty example.

Note that you can do this without using a UserControl. I'm just staying within the confines of your description.

User Control

<UserControl>
    <UserControl.Resources>
        <ControlTemplate x:Key="usingColumns">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*" />
                    <ColumnDefinition Width="*" />
                </Grid.ColumnDefinitions>

                <ListBox Grid.Column="0" ItemsSource="{Binding DataOneItems}" />
                <ListBox Grid.Column="1" ItemsSource="{Binding DataTwoItems}" />
            </Grid>

        </ControlTemplate>
        <ControlTemplate x:Key="usingRows">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="*" />
                    <RowDefinition Height="*" />
                </Grid.RowDefinitions>

                <ListBox Grid.Row="0" ItemsSource="{Binding DataOneItems}" />
                <ListBox Grid.Row="1" ItemsSource="{Binding DataTwoItems}" />
            </Grid>
        </ControlTemplate>
    </UserControl.Resources>
    <UserControl.Style>
        <Style>
            <Setter Property="UserControl.Template" Value="{StaticResource usingColumns}" />
            <Style.Triggers>
                <DataTrigger Binding="{Binding ShowVertically}" Value="true">
                    <Setter Property="UserControl.Template" Value="{StaticResource usingRows}" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </UserControl.Style>
</UserControl>

Class binding to User Control:

public class UserControlData
{
    public ReadOnlyObservableCollection<DataTypeOne> DataOneItems
    {
        get
        {
            ObservableCollection<DataTypeOne> dataOneItems = new ObservableCollection<DataTypeOne>();
            for (int i = 1; i <= 3; i++)
                dataOneItems.Add(new DataTypeOne(i));

            return new ReadOnlyObservableCollection<DataTypeOne>(dataOneItems);
        }
    }

    public ReadOnlyObservableCollection<DataTypeTwo> DataTwoItems
    {
        get
        {
            ObservableCollection<DataTypeTwo> dataTwoItems = new ObservableCollection<DataTypeTwo>();
            for (int i = 1; i <= 3; i++)
                dataTwoItems.Add(new DataTypeTwo(i));

            return new ReadOnlyObservableCollection<DataTypeTwo>(dataTwoItems);
        }
    }

    public bool ShowVertically
    {
        get;
        set;
    }
}

Dummy Data Type (DataTypeOne and DataTypeTwo are identical except in class name):

public class DataTypeOne
{
    private readonly int mId = 0;

    public DataTypeOne(int id)
    {
        mId = id;
    }

    public int ID
    {
        get { return mId; }
    }

    public override string ToString()
    {
        return String.Format("I am a DataTypeOne with ID {0}", mId.ToString("N"));
    }
}

The key is the ControlTemplates (one for horizontal, one for vertical) and the DataTrigger on the Style.

Mugiwara
  • 866
  • 1
  • 11
  • 33
Wonko the Sane
  • 10,623
  • 8
  • 67
  • 92
  • Thank's for the answer. I'm new to WPF and need some clarifications. Let's say the ListBox you are using in the ControlTemplate has a name ListBoxName and you wan to reference it from the code behind like this: this.ListBoxName. What would be the way to do it, since it is inside of the ControlTemplate, the code behind produces a compile error saying that my xaml does not contain a definition for ListBoxName... Thank you – user1801115 Nov 09 '12 at 15:07
  • Here's [one of many](http://stackoverflow.com/questions/820201/how-to-access-a-wpf-control-located-in-a-controltemplate) examples here on SO, or just Google it. – Wonko the Sane Nov 09 '12 at 20:42