Я пытаюсь добиться определенного изменения размера в нижнем колонтитуле приложения, которое имеет следующую общую структуру xaml:
<Window>
<Window.DataContext>
<local:MainWindowViewModel />
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height = "Auto"/>
<RowDefinition Height = "Auto"/>
<RowDefinition Height = "*"/>
<RowDefinition Height = "Auto"/>
</Grid.RowDefinitions>
...
<Grid Grid.Row = "3" Grid.Column = "0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width = "Auto" />
<ColumnDefinition Width = "Auto" />
<ColumnDefinition Width = "*" />
<ColumnDefinition Width = "Auto" />
<ColumnDefinition Width = "Auto" />
</Grid.ColumnDefinitions>
<CheckBox Grid.Column = "0" VerticalContentAlignment = "Center" VerticalAlignment = "Center" Padding = "2,0" Content = "Checkbox" />
<TextBlock Grid.Column = "1" Margin = "10,0,0,0" VerticalAlignment = "Center" Text = "Log Folder: " />
<TextBox Grid.Column = "2" Height = "24" VerticalAlignment = "Center" VerticalContentAlignment = "Center" Padding = "2" Focusable = "False" IsReadOnly = "True" Cursor = "Hand" Text = "{Binding LogFolder}" />
<Button Grid.Column = "3" Height = "24" Width = "24" Margin = "4,0" VerticalAlignment = "Center" Command = "{Binding SelectFolderCommand}">
<Button.Content>
<Image Width = "16" Height = "16" Source = "/Images/Refresh.png" />
</Button.Content>
</Button>
<Button Grid.Column = "4" VerticalAlignment = "Center" HorizontalAlignment = "Right" Content = " Button " />
</Grid>
</Grid>
</Window>
В нижнем колонтитуле текстовое поле обрезается, если недостаточно места по горизонтали для отображения всего пути:
Когда места более чем достаточно, текстовое поле расширяется по горизонтали, чтобы заполнить доступное пространство:
Хотя первое поведение желательно, во втором случае мне бы хотелось, чтобы текстовое поле не расширялось и не заполняло все доступное пространство. Скорее, я бы хотел, чтобы текстовое поле расширялось ровно настолько, чтобы отобразить весь путь, а затем чтобы левая кнопка оставалась рядом с ним, а между двумя кнопками появлялось любое лишнее пространство, как в этом макете:
Я попробовал обернуть текстовое поле и левую кнопку во вложенную сетку следующим образом:
<Grid Grid.Row = "3" Grid.Column = "0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width = "Auto" />
<ColumnDefinition Width = "Auto" />
<ColumnDefinition Width = "*" />
<ColumnDefinition Width = "Auto" />
</Grid.ColumnDefinitions>
<CheckBox Grid.Column = "0" VerticalContentAlignment = "Center" VerticalAlignment = "Center" Padding = "2,0" Content = "Checkbox" />
<TextBlock Grid.Column = "1" Margin = "10,0,0,0" VerticalAlignment = "Center" Text = "Log Folder: " />
<Grid Grid.Column = "2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width = "Auto" />
<ColumnDefinition Width = "*" />
</Grid.ColumnDefinitions>
<TextBox Grid.Column = "0" Height = "24" VerticalAlignment = "Center" VerticalContentAlignment = "Center" Padding = "2" Focusable = "False" IsReadOnly = "True" Cursor = "Hand" Text = "{Binding LogFolder}" />
<Button Grid.Column = "1" Height = "24" Width = "24" Margin = "4,0" HorizontalAlignment = "Left" VerticalAlignment = "Center" Command = "{Binding SelectFolderCommand}">
<Button.Content>
<Image Width = "16" Height = "16" Source = "/Images/Refresh.png" />
</Button.Content>
</Button>
</Grid>
<Button Grid.Column = "4" VerticalAlignment = "Center" HorizontalAlignment = "Right" Content = " Button " />
</Grid>
Хотя это и обеспечивает желаемое поведение, когда места более чем достаточно, когда места недостаточно, левая кнопка перегружена:
Помимо этого, я пробовал множество других вариантов замены ширины Auto
и *
для столбцов сеток, обертывания вещей в StackPanels, закрепления вещей в DockPanels и добавления дополнительных сеток, но я могу достичь только одного из двух ранее описанных наборы поведения. Т.е. либо левая кнопка не переполняется, когда окно узкое, но текстовое поле расширяется без границ, когда окно широкое, либо расширение текстового поля ограничено, когда окно широкое, но левая кнопка переполняется, когда окно узкое .
Достижимо ли поведение, которое я ищу? Предпочтительны ответы на чистом xaml, но если я могу добиться этого только с помощью кода в выделенном коде, модели представления или преобразователя, пусть будет так.
Вы можете использовать прокси-элементы для измерения и установки размера. Посмотрите на этот пример:
<Grid Grid.Row = "3" Grid.Column = "0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width = "Auto" />
<ColumnDefinition Width = "Auto" />
<ColumnDefinition Width = "*" />
<ColumnDefinition Width = "Auto" />
<ColumnDefinition Width = "Auto" />
</Grid.ColumnDefinitions>
<CheckBox Grid.Column = "0" VerticalContentAlignment = "Center" VerticalAlignment = "Center" Padding = "2,0" Content = "Checkbox" />
<TextBlock Grid.Column = "1" Margin = "10,0,0,0" VerticalAlignment = "Center" Text = "Log Folder: " />
<FrameworkElement Grid.Column = "2" x:Name = "sizeSource"/>
<FrameworkElement Grid.Column = "3"
Width = "{Binding ActualWidth, ElementName=btnSource, Mode=OneWay}"
Margin = "{Binding Margin, ElementName=btnSource, Mode=OneWay}"/>
<StackPanel Grid.Column = "2" Grid.ColumnSpan = "2" Orientation = "Horizontal">
<TextBox Height = "24" VerticalAlignment = "Center" VerticalContentAlignment = "Center" Padding = "2" Focusable = "False" Cursor = "Hand"
MinWidth = "40" MaxWidth = "{Binding ActualWidth, ElementName=sizeSource, Mode=OneWay}"/>
<Button x:Name = "btnSource" Height = "24" Width = "24" Margin = "4,0" VerticalAlignment = "Center" Command = "{Binding SelectFolderCommand}">
<Button.Content>
<Image Width = "16" Height = "16" Source = "/Source/CenterPicture.png" />
</Button.Content>
</Button>
</StackPanel>
<Button x:Name = "button" Grid.Column = "4" VerticalAlignment = "Center" HorizontalAlignment = "Right" Content = " Button " />
</Grid>
Кажется, это работает! Мне нравится этот трюк, и я постараюсь запомнить его. Спасибо! Я приму это в свое время, если не появится лучших ответов.
Должен признаться, я удивлен тем, что привязка FrameworkElement
в столбце 3 к ElementName
к btnSource
работает. Я всегда думал, что ElementName
должен работать только тогда, когда элемент, на который вы ссылались, уже был определен ранее.
@Joe Binding ElementName
обеспечивает динамическую привязку. Например, вы можете переназначить FrameworkElement.RegisterName(String, Object)
во время выполнения в любое время в течение жизни окна, и значение Binding ElementName
будет переоценено.
Вложенные сетки, которые у вас уже есть, будут работать как положено.
Вам просто нужно обязательно установить HorizontalAlignment = "Left"
на внутренней сетке и использовать ширину столбцов *
и Auto
в указанном порядке.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width = "Auto"/>
<ColumnDefinition Width = "Auto"/>
<ColumnDefinition Width = "*"/>
<ColumnDefinition Width = "Auto"/>
</Grid.ColumnDefinitions>
<CheckBox Grid.Column = "0" Content = "Checkbox" Padding = "2,0"
VerticalAlignment = "Center" VerticalContentAlignment = "Center" />
<TextBlock Grid.Column = "1" Margin = "10,0,0,0"
VerticalAlignment = "Center" Text = "Log Folder: " />
<Grid Grid.Column = "2" HorizontalAlignment = "Left" VerticalAlignment = "Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width = "*"/>
<ColumnDefinition Width = "Auto"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column = "0" Height = "24" Padding = "2"
VerticalContentAlignment = "Center" Focusable = "False"
IsReadOnly = "True" Cursor = "Hand" Text = "{Binding LogFolder}" />
<Button Grid.Column = "1" Height = "24" Width = "24" Margin = "4,0"
Command = "{Binding SelectFolderCommand}">
<Image Width = "16" Height = "16" Source = "/Images/Refresh.png" />
</Button>
</Grid>
<Button Grid.Column = "3" VerticalAlignment = "Center" Content = " Button " />
</Grid>
Вау, это было так просто. Я предполагал, что HorizontalAlignment = "Left"
используется по умолчанию для всего, и не стал это пробовать.
Значением по умолчанию для HorizontalAlignment и UpperAlignment является Stretch.
Ах, я вижу. Я объединял TextAlignment с HorizontalAlignment. Спасибо за знания!
Если вы хотите «подвесить» правый столбец, в какой-то момент вам придется ограничить размер контейнера; в противном случае он просто будет продолжать разрушаться сам по себе. Столбец «звездочка» ничего не значит, если вообще нет «свободного места», на которое можно «претендовать».