Хобрук: Ваш путь к мастерству в программировании

Нежелательное изменение размера кнопки после преобразования

Я пытаюсь создать расширяемое/складное меню для моего личного проекта. У меня есть все почти там, где я этого хочу (в любом случае, с точки зрения того, что он ведет себя так, как ожидалось). Когда я сворачиваю свое меню, я хочу, чтобы кнопки поворачивались в вертикальное положение и не изменяли размер (или, по крайней мере, изменяли размер до того, что все еще соответствует тексту). На данный момент кнопки поворачиваются, затем сжимаются по вертикали (какова была/есть ширина) вместе с родительским элементом управления, который обрезает большую часть содержимого. Я понимаю, почему это могло произойти, но не могу придумать способ обойти это, который кажется мне правильным.

Вот что я вижу:
Раньше: До После: После

Как вы можете видеть, кнопки сжимаются по своей теперь вертикальной ширине (я предполагаю, что это будет ширина окружающего StackPanel).

Вот код, который я использую:

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
}  

Если вы хотите протестировать код, он должен работать в обычной сетке, как у меня (вышеупомянутые элементы управления UserControl, которые я сделал, находятся в папке Controls внутри проекта):

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

После того, как все сказано и сделано, вот поведение/внешний вид, который мне нужен (кнопки уведомлений не сокращены)Желаемый вид

12.07.2016

Ответы:


1

Причиной макета, который вы видите, является ограничение фиксированной высоты, которое вы установили в ExpandingMenuButton: Height="30" как для элемента UserControl, так и для элемента Grid. Вы можете изменить его на MinHeight.

Кроме того, когда вы устанавливаете ширину MenuPanel, вы также содержите высоту кнопок, потому что вы применяете преобразование.

Вот один из способов исправить это:

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>

Как правило, не указывайте ширину и высоту в WPF — пусть система макета сделает за вас измерения в соответствии с содержимым.

12.07.2016
  • Я изменил Height на MinHeight на ExpandingMenuButton UserControl и добавил его в StackPanel на ExpandingMenu, но поведение такое же. Я что-то неправильно понял? 13.07.2016
  • Вам также нужно изменить эту высоту: <Grid Name="ButtonGrid" Height="30"> 13.07.2016
  • Вам это не нужно на StackPanel. Я перепутал его с Grid. 13.07.2016
  • Это по-прежнему не влияет на то, как он выглядит. Смотрите мое редактирование для скриншота того, что мне нужно, на случай, если я недостаточно ясно описал что-то. 13.07.2016
  • Ваше вышеприведенное решение, кажется, работает довольно хорошо, но есть ли способ заставить их складывать сверху вниз? Кажется, что ExpandingMenuButton начинаются снизу и складываются вверх. 13.07.2016
  • Вы действительно должны узнать больше о макете WPF, стилях и привязке данных. Вы не используете имеющиеся в вашем распоряжении инструменты. Я предлагаю вам прочитать WPF Unleashed — это действительно хорошая книга для начинающих. 13.07.2016
  • Да, из WinForms это определенно непросто. У меня есть доставка книги, но я пытаюсь извлечь из этого как можно больше пользы, играя с ней. По крайней мере, я чувствую, что я близок... Всего один вопрос. 13.07.2016
  • Я обновил код... также, пожалуйста, проголосуйте и примите ответ :) 13.07.2016
  • Ух ты! Спасибо, это действительно интересно :) Думаю, остаток вечера я буду читать этот код и понимать, что он делает! Спасибо еще раз! 13.07.2016
  • Обратите внимание, как я избегал всех этих «магических чисел» в коде... вы должны сделать то же самое. Макет WPF очень мощный. 13.07.2016
  • Я согласен. Я точно вижу силу. Это так... заманчиво попробовать использовать абсолюты, как с WinForms. Я обязательно последую вашему совету и проверю себя на практике, если поймаю себя на этом! не говоря уже о том, что моим инстинктом было вычислить решение для ширины отдельных кнопок ... грубо. но, по крайней мере, у меня хватило здравого смысла понять, что это неправильно, и прийти сюда за помощью! 13.07.2016
  • Новые материалы

    Создание кнопочного меню с использованием HTML, CSS и JavaScript
    Вы будете создавать кнопочное меню, которое имеет состояние наведения, а также позволяет вам выбирать кнопку при нажатии на нее. Финальный проект можно увидеть в этом Codepen . Шаг 1..

    Внедрите OAuth в свои веб-приложения для повышения безопасности
    OAuth — это широко распространенный стандарт авторизации, который позволяет приложениям получать доступ к ресурсам от имени пользователя, не раскрывая его пароль. Это позволяет пользователям..

    Классы в JavaScript
    class является образцом java Script Object. Конструкция «class» позволяет определять классы на основе прототипов с чистым, красивым синтаксисом. // define class Human class Human {..

    Как свинг-трейдеры могут использовать ИИ для больших выигрышей
    По мере того как все больше и больше профессиональных трейдеров и активных розничных трейдеров узнают о возможностях, которые предоставляет искусственный интеллект и машинное обучение для улучшения..

    Как построить любой стол
    Я разработчик программного обеспечения. Я люблю делать вещи и всегда любил. Для меня программирование всегда было способом создавать вещи, используя только компьютер и мое воображение...

    Обзор: Машинное обучение: классификация
    Только что закончил третий курс курса 4 часть специализации по машинному обучению . Как и второй курс, он был посвящен низкоуровневой работе алгоритмов машинного обучения. Что касается..

    Разработка расширений Qlik Sense с qExt
    Использование современных инструментов веб-разработки для разработки крутых расширений Вы когда-нибудь хотели кнопку для установки переменной в приложении Qlik Sense? Когда-нибудь просили..