WPF: сетка с полями столбцов/строк / заполнением?
можно ли легко указать поле и / или заполнение для строк или столбцов в сетке WPF?
Я мог бы, конечно, добавить дополнительные столбцы для пробелов, но это похоже на работу для заполнения / полей (это даст много более простой XAML). Кто-то получил от стандартной сетки, чтобы добавить эту функциональность?
13 ответов:
вы могли бы написать свой собственный
GridWithMarginкласс, унаследованный отGridи переопределитьArrangeOverrideметод применения полей
RowDefinitionиColumnDefinitionтипаContentElementиMarginстрого aFrameworkElementсобственность. Так что на ваш вопрос,"это легко можно" ответ Определенно нет. И нет, я не видел никаких макетных панелей, которые демонстрируют такую функциональность.вы можете добавлять дополнительные строки или столбцы, как вы предложили. Но вы также можете установить поля на
Gridсам элемент, или все, что будет идти внутриGrid, так что это ваш лучший обходной путь для сейчас.
использовать
Borderуправление вне элемента управления ячейки и определить заполнение для этого:<Grid> <Grid.Resources > <Style TargetType="Border" > <Setter Property="Padding" Value="5,5,5,5" /> </Style> </Grid.Resources> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <Border Grid.Row="0" Grid.Column="0"> <YourGridControls/> </Border> <Border Grid.Row="1" Grid.Column="0"> <YourGridControls/> </Border> </Grid>
Источник:
вы могли бы использовать что-то вроде этого:
<Style TargetType="{x:Type DataGridCell}"> <Setter Property="Padding" Value="4" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type DataGridCell}"> <Border Padding="{TemplateBinding Padding}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True"> <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> </Border> </ControlTemplate> </Setter.Value> </Setter>или если вам не нужны TemplateBindings:
<Style TargetType="{x:Type DataGridCell}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type DataGridCell}"> <Border Padding="4"> <ContentPresenter /> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style>
думал, что я добавлю свое собственное решение, потому что никто еще не упоминал об этом. Вместо конструирования пользовательских элементов управления на основе сетки, вы можете ориентироваться на элементы управления, содержащиеся в сетку с декларацией стиль. Заботится о добавлении заполнения / поля для всех элементов без необходимости определять для каждого, что является громоздким и трудоемким.Например, если ваша сетка не содержит ничего, кроме текстовых блоков, вы можете сделать это:
<Style TargetType="{x:Type TextBlock}"> <Setter Property="Margin" Value="10"/> </Style>Это типа как "ячейки".
Я сделал это прямо сейчас с одной из моих сеток.
- сначала примените одно и то же поле к каждому элементу внутри сетки. Вы можете сделать это mannualy, используя стили, или все, что вам нравится. Допустим, вы хотите горизонтальный интервал 6px и вертикальный интервал 2px. Затем вы добавляете поля "3px 1px" к каждому дочернему элементу сетки.
- затем удалите поля, созданные вокруг сетки (если вы хотите выровнять границы элементов управления внутри сетки в том же положении сетка.) Сделайте это, установив поле "- 3px-1px " к сетке. Таким образом, другие элементы управления вне сетки будут выровнены с самыми внешними элементами управления внутри сетки.
я столкнулся с этой проблемой недавно, разработке программного обеспечения, и мне пришло в голову спросить, почему? Зачем они это сделали...ответ был прямо передо мной. Строка данных является объектом, поэтому если мы сохраняем ориентацию объекта, то дизайн для конкретной строки должен быть разделен (предположим, что вам нужно повторно использовать отображение строки позже в будущем). Поэтому я начал использовать панели стека databound и пользовательские элементы управления для большинства дисплеев данных. Списки сделали случайное появление но в основном сетка использовалась только для организации первичной страницы (заголовок, область меню, область содержимого, другие области). Ваши пользовательские объекты могут легко управлять любыми требованиями к расстоянию для каждой строки в панели стека или сетке (одна ячейка сетки может содержать весь объект строки. Это также имеет дополнительное преимущество правильной реакции на изменения ориентации, расширение / свертывание и т. д.
<Grid> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <custom:MyRowObject Style="YourStyleHereOrGeneralSetter" Grid.Row="0" /> <custom:MyRowObject Style="YourStyleHere" Grid.Row="1" /> </Grid>или
<StackPanel> <custom:MyRowObject Style="YourStyleHere" Grid.Row="0" /> <custom:MyRowObject Style="YourStyleHere" Grid.Row="1" /> </StackPanel>ваши пользовательские элементы управления также наследуют DataContext, если использование привязки данных...мой любимый пользу такого подхода.
Как было указано ранее, создайте класс GridWithMargins. Вот мой рабочий пример кода
public class GridWithMargins : Grid { public Thickness RowMargin { get; set; } = new Thickness(10, 10, 10, 10); protected override Size ArrangeOverride(Size arrangeSize) { var basesize = base.ArrangeOverride(arrangeSize); foreach (UIElement child in InternalChildren) { var pos = GetPosition(child); pos.X += RowMargin.Left; pos.Y += RowMargin.Top; var actual = child.RenderSize; actual.Width -= (RowMargin.Left + RowMargin.Right); actual.Height -= (RowMargin.Top + RowMargin.Bottom); var rec = new Rect(pos, actual); child.Arrange(rec); } return arrangeSize; } private Point GetPosition(Visual element) { var posTransForm = element.TransformToAncestor(this); var areaTransForm = posTransForm.Transform(new Point(0, 0)); return areaTransForm; } } <Window x:Class="WpfApplication1.MainWindow" 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:WpfApplication1" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525"> <Grid> <local:GridWithMargins ShowGridLines="True"> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition /> <ColumnDefinition /> </Grid.ColumnDefinitions> <Rectangle Fill="Red" Grid.Row="0" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" /> <Rectangle Fill="Green" Grid.Row="1" Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" /> <Rectangle Fill="Blue" Grid.Row="1" Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" /> </local:GridWithMargins> </Grid> </Window>
одной из возможностей было бы добавить фиксированную ширину строк и столбцов, чтобы действовать в качестве заполнения / поля, которое вы ищете.
вы также можете считать, что вы ограничены размером вашего контейнера, и что сетка станет такой же большой, как содержащий элемент или его заданная ширина и высота. Вы можете просто использовать столбцы и строки без набора ширины или высоты. Таким образом, они по умолчанию равномерно разбивают общее пространство в сетке. Тогда это будет просто вопрос центрирование элементов по вертикали и горизонтали внутри сетки.
другой метод может заключаться в том, чтобы обернуть все элементы сетки в фиксированную сетку с одной строкой и столбцом, которая имеет фиксированный размер и поле. Что ваша сетка содержит фиксированные поля ширины / высоты, которые содержат ваши фактические элементы.
Я удивлен, что я еще не видел это решение опубликовано.
исходя из интернета, фреймворки, такие как bootstrap, будут использовать отрицательное поле для возврата строк / столбцов.
это может быть немного многословным (хотя и не так уж плохо), он работает, и элементы равномерно распределены и имеют размер.
в примере ниже я использую
StackPanelroot, чтобы продемонстрировать, как 3 кнопки равномерно расположены с помощью полей. Вы можете использовать другие элементы, просто измените внутренний x: Type от кнопки до вашего элемента.идея проста, используйте сетку снаружи, чтобы вытащить поля элементов из их границ на половину объема внутренней сетки (используя отрицательные поля), используйте внутреннюю сетку, чтобы равномерно распределить элементы с требуемой суммой.
<StackPanel> <Grid> <Grid.Resources> <Style TargetType="{x:Type Grid}"> <Setter Property="Margin" Value="-5 0"/> </Style> </Grid.Resources> <Grid> <Grid.Resources> <Style TargetType="{x:Type Button}"> <Setter Property="Margin" Value="10 0"/> </Style> </Grid.Resources> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Button Grid.Column="0" Content="Btn 1" /> <Button Grid.Column="1" Content="Btn 2" /> <Button Grid.Column="2" Content="Btn 3" /> </Grid> </Grid> <TextBlock FontWeight="Bold" Margin="0 10"> Test </TextBlock> </StackPanel>
хотя вы не можете добавить поля или отступы к сетке, вы можете использовать что-то вроде фрейма (или аналогичного контейнера), к которому вы можете применить его.
таким образом (если вы показываете или скрываете элемент управления при нажатии кнопки say), вам не нужно будет добавлять маржу на каждый элемент управления, который может взаимодействовать с ним.
думайте об этом как об изоляции групп элементов управления в единицы, а затем о применении стиля к этим единицам.
Иногда простой метод является лучшим. Просто дополните свои строки пробелами. Если это только несколько текстовых полей и т. д. Это самый простой способ.
вы также можете просто вставить пустые столбцы/строки с фиксированным размером. Очень простые и вы можете легко изменить его.

Comments