Как я могу ограничить высоту контейнера до высоты определенного элемента содержимого? - PullRequest
2 голосов
/ 12 июня 2010

Я пытаюсь сделать что-то, что кажется очень простым, и все же я не понимаю, как это сделать.У меня очень простой макет, TextBox с изображением рядом с ним, похожий на то, как он может выглядеть, украшенный ErrorProvider в приложении WinForms.Проблема в том, что я хочу, чтобы изображение было не выше TextBox, рядом с которым оно находится.Если я выложу это так, скажем:

<Grid>  
  <Grid.RowDefinitions>
    <RowDefinition Height="Auto"/>
  </Grid.RowDefinitions>
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="Auto"/>
    <ColumnDefinition Width="Auto"/>
  </Grid.ColumnDefinitions>
  <TextBox Grid.Row="0" Grid.Column="0" MinWidth="100"/>
  <Image Grid.Row="0" Grid.Column="1" Source="error.png" />
</Grid>

строка будет размером с высоту изображения, если изображение будет выше, чем TextBox.Это также происходит, если я использую DockPanel или StackPanel.

Наивным решением было бы связать Height с TextBox ActualHeight.Я уверен, что это неправильно.Но что правильно?

Редактировать

Вот пример того, что мне кажется неправильным: в обоих этих макетах (оба горизонтальных StackPanel с)FontSize является единственной переменной:

Two examples showing unscaled icons

Вы можете видеть, что первое TextBox ограничено высотой значка и в результате имеет ненужный нижний отступпод текстом.И значок рядом со вторым не соответствует масштабу TextBox рядом с ним.

Когда это случилось, я нашел совершенно другой (и гораздо лучший) способ решения проблемы - изначально я масштабировалмой макет, изменив FontSize на Window, но использование ScaleTransform намного проще и, кажется, работает отлично.Но даже в этом случае мне все еще кажется странным, что это так трудно сделать.

Ответы [ 2 ]

2 голосов
/ 12 июня 2010

Назовите свой TextBox, укажите ссылку на TextBox из картинки следующим образом.

<TextBox Name="myTextBox" 
         Grid.Row="0" Grid.Column="0" 
         MinWidth="100"/> 
<Image Grid.Row="0" 
       Grid.Column="1" 
       Source="error.png" 
       Height="{Binding ActualHeight, ElementName=myTextBox}"/> 
1 голос
/ 31 июля 2010

Требуется алгоритм компоновки, который измеряет другие элементы с ограничением высоты, равным требуемой высоте конкретного.Хотя некоторые из существующих реализаций Panel уменьшат доступное пространство для оставшихся элементов в зависимости от размера, используемого предыдущими, ни одна из них не установит ограничение так, как вы хотите.Если вы хотите описать поведение, которое вы описываете за один проход макета, вам нужно написать собственный алгоритм макета.

Например, вы можете приблизиться, переопределив поведение StackPanel следующим образом:

public class SizeToFirstChildStackPanel
    : StackPanel
{
    protected override Size MeasureOverride(Size constraint)
    {
        if (Children.Count > 0)
        {
            var firstChild = Children[0];
            firstChild.Measure(constraint);
            if (Orientation == Orientation.Horizontal)
            {
                constraint = new Size(
                    constraint.Width,
                    Math.Min(firstChild.DesiredSize.Height, constraint.Height));
            }
            else
            {
                constraint = new Size(
                    Math.Min(firstChild.DesiredSize.Width, constraint.Width),
                    constraint.Height);
            }
        }
        return base.MeasureOverride(constraint);
    }
}

Это ограничит высоту всех дочерних элементов StackPanel до желаемой высоты первого из них.(или ширина, если панель ориентирована вертикально).

Это все еще не идеально, потому что первый дочерний элемент будет измерен во второй раз базовым классом MeasureOverride, а второй показатель будет иметь ограничение.Это дополнительная работа, которая вызовет странное поведение, если первый ребенок захочет стать больше.

Чтобы сделать это правильно, вам нужно самостоятельно реализовать весь метод метода MeasureOverride.Я не собираюсь делать это здесь, потому что это будет много кода, который на самом деле не имеет отношения к проблеме, и это зависит от того, как именно вы хотите, чтобы макет работал.Важный момент заключается в том, чтобы сначала измерить определенный элемент и использовать его DesiredSize, чтобы определить доступный размер при вызове Measure для других.

...