Broots Waymb
Broots Waymb

Reputation: 4826

Undesired button resizing after being transformed

I'm trying to create an expandable/collapsible menu for a personal project of mine. I have everything almost where I want it (in terms of it being behaving as expected anyway). When I collapse my menu, I want the buttons to rotate to a vertical position and not resize (Or at least resize to something that still fits the text). At the moment, the buttons rotate, then shrink vertically (what was/is the width) along with the parent control, which cuts off much of the contents. I can see why this would happen, but I can't think of a way around it that seems right to me.

Here is the behavior I'm seeing:
Before: Before After: After

As you can see, the buttons are shrinking along their now-vertical width (to what I assume would be the width of the enclosing StackPanel).

Here is the code I am using:

ExpaningMenu.xaml

<UserControl x:Class="Budgety.Controls.ExpandingMenu"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:Budgety.Controls"
         mc:Ignorable="d"
         Name="MainExpandingMenu"
         MinWidth="32"
         d:DesignHeight="300" d:DesignWidth="100"> 
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition />
    </Grid.RowDefinitions>
    <StackPanel Name="MenuPanel" Width="100" HorizontalAlignment="Left" Background="{DynamicResource BackColor}" Grid.Row="1">
        <!--Contents will go here-->
    </StackPanel>
    <Button Name="StateToggle" Width="100" Height="32" FontSize="18" VerticalAlignment="Center" HorizontalAlignment="Stretch" Panel.ZIndex="1" Background="{DynamicResource BackColor}" BorderThickness="0" Click="Button_Click" Content="&#171;"></Button>
</Grid>
</UserControl>

ExpandingMenu.xaml.cs

public partial class ExpandingMenu : UserControl
{
    public ExpandingMenu()
    {
        InitializeComponent();

        //For testing purposes.
        MenuPanel.Children.Add(new ExpandingMenuButton("TEST ITEM 1"));
        MenuPanel.Children.Add(new ExpandingMenuButton("TEST ITEM 2"));
        MenuPanel.Children.Add(new ExpandingMenuButton("TEST ITEM 3"));
        MenuPanel.Children.Add(new ExpandingMenuButton("TEST ITEM 4"));
        MenuPanel.Children.Add(new ExpandingMenuButton("TEST ITEM 5xxx"));

        foreach (UIElement element in MenuPanel.Children)
        {
            (element as ExpandingMenuButton).HorizontalAlignment = HorizontalAlignment.Left;
        }
    }

    #region Events
    private void Button_Click(object sender, RoutedEventArgs e)
    {
        if (MenuPanel.Width == 100) //Need to collapse
        {
            StateToggle.Width = MenuPanel.Width = 32;

            (sender as Button).Content = "\u00BB";

            //Flip all children of this control (so far, assuming only ExpandingMenuButtons)
            foreach (UIElement element in MenuPanel.Children)
            {
                (element as ExpandingMenuButton).LayoutTransform = new RotateTransform(-90);

                //This works to resize to 100 tall (not ideal...)
                //(element as ExpandingMenuButton).Width = 100;
                //This does not seem to size to auto, which SHOULD make each button as long as the text requires... (this behavior is far less than ideal...)
                //(element as ExpandingMenuButton).Width = Double.NaN;
            }
        }
        else //Need to expand
        {
            StateToggle.Width = MenuPanel.Width = 100;
            (sender as Button).Content = "\u00AB";

            //Flip all children of this control (so far, assuming only ExpandingMenuButtons)
            foreach (UIElement element in MenuPanel.Children)
            {
                (element as ExpandingMenuButton).LayoutTransform = new RotateTransform(0);
            }
        }
    }
    #endregion
}  

ExpandingMenuButton.xaml

<UserControl x:Class="Budgety.Controls.ExpandingMenuButton"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:Budgety.Controls"
         mc:Ignorable="d" 
         d:DesignHeight="30" d:DesignWidth="100"
         Height="30"
         Name="ButtonControl">
<Grid Name="ButtonGrid" Height="30">
    <ToggleButton Name="MenuButton" Background="Aqua" BorderThickness="1" Content="TEST"></ToggleButton>
</Grid>
</UserControl>  

ExpandingMenuButton.xaml.cs

public partial class ExpandingMenuButton : UserControl
{
    //Will definitely want custom functionalty here. TBD. Nothing special so far.

    #region Constructors
    public ExpandingMenuButton()
    {
        InitializeComponent();
    }

    public ExpandingMenuButton(string sText)
    {
        InitializeComponent();

        MenuButton.Content = sText;
    }
    #endregion
}  

If you'd like to test the code out, it should work placed in a normal grid as I have (The above mentioned UserControls I've made are in a Controls folder within the project):

<Window
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:Budgety"
    xmlns:Controls="clr-namespace:Budgety.Controls" x:Class="Budgety.MainTest"
    mc:Ignorable="d"
    Title="MainTest" Height="600" Width="800">
<Grid>
    <Controls:ExpandingMenu x:Name="ExpandingMenu" HorizontalAlignment="Left"/>
</Grid>
</Window>  

After all is said and done, here is the behavior/look I am after (notice buttons are not shortened)Desired look

Upvotes: 3

Views: 48

Answers (1)

Eli Arbel
Eli Arbel

Reputation: 22739

The reason for the layout you're seeing is the fixed height constraint you placed in ExpandingMenuButton: Height="30" on both the UserControl and the Grid element. You can change it to MinHeight.

In addition, when you set the width of the MenuPanel, you're also containing the height of the buttons, because you apply a transform.

Here's one way to fix this:

private void Button_Click(object sender, RoutedEventArgs e)
{
    if (StateToggle.IsChecked == true)
    {
        StateToggle.Content = "\u00BB";
        foreach (FrameworkElement element in MenuPanel.Children)
            element.LayoutTransform = new RotateTransform(-90);
    }
    else
    {
        StateToggle.Content = "\u00AB";
        foreach (FrameworkElement element in MenuPanel.Children)
            element.LayoutTransform = null;
    }
}

XAML:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto" />
        <RowDefinition />
    </Grid.RowDefinitions>
    <StackPanel Name="MenuPanel"
                HorizontalAlignment="Left"
                Background="{DynamicResource BackColor}"
                Grid.Row="1">
        <!--Contents will go here-->
    </StackPanel>
    <ToggleButton Name="StateToggle"
                  FontSize="18"
                  VerticalAlignment="Center"
                  HorizontalAlignment="Stretch"
                  Panel.ZIndex="1"
                  Background="{DynamicResource BackColor}"
                  BorderThickness="0"
                  Click="Button_Click"
                  Content="&#171;" />
</Grid>

As a general rule, don't specify widths and heights in WPF - let the layout system do the measuring for you according to the content.

Upvotes: 1

Related Questions