Как создать форму в WPF с помощью сетки или других элементов управления для удобства обслуживания
У меня есть форма WPF, я хочу выложить на него стандартную форму. Каждый элемент формы будет иметь метку, а затем элемент управления. Довольно стандартный материал.
Если я использую панель обертки, это может привести к разделению метки и элемента управления, но я хочу, чтобы они оставались вместе. Есть ли какой-либо WPF-эквивалент <nobr/>
?
Сетка работает, а также позволяет перекрывать столбцы и т.д., однако я действительно очень ненавижу, что вы указываете столбец и строку для каждого элемента управления. Это делает крайне неудобным переупорядочивать или вставлять вещи в список.
Есть ли способ получить сетку для использования большего количества столбцов/строк HTML-стиля, где элементы являются дочерними элементами строки, в которой они находятся, чтобы я мог легко переупорядочить?
Есть ли какой-нибудь другой элемент управления, который позволит мне легко разместить форму?
Ответы
Ответ 1
есть ли какой-либо WPF-эквивалент nobr?
Помните, что вы можете вставлять панели:
<WrapPanel Orientation="Horizontal">
<StackPanel Orientation="Horizontal">
<Label>Some field</Label>
<TextBox>Some value</TextBox>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label>Another field</Label>
<TextBox>Another value</TextBox>
</StackPanel>
...
</WrapPanel>
Кроме того, для столбчатых макетов общая область сетки Grid может координировать любое количество сеток, которые ее используют:
<StackPanel Orientation="Vertical" Grid.IsSharedSizeScope="True">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="Label"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0">Some field</Label>
<TextBox Grid.Column="1">Some value</TextBox>
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="Label"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0">Another field</Label>
<TextBox Grid.Column="1">Another value</TextBox>
</Grid>
</StackPanel>
Я ненавижу как многословный XAML для этого, тем более что вам нужно повторить определения столбцов. Хотя, если вы правильно структурируете свои классы и используете шаблоны, это не так страшно. И обратите внимание, что вы не отслеживаете номера строк в этой схеме, поэтому поля переупорядочения просты.
Ответ 2
Попробуйте использовать элемент управления UniformGrid.
Ответ 3
То, что вы, возможно, ищете, представляет собой панель стека. Использование вертикальной StackPanel позволит вам упорядочить ярлык и элементы управления. Для каждой метки и элемента управления вам может понадобиться горизонтальная панель стека, например
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<Label Width="150">Name</Label>
<Textbox Width="200/>
</StackPanel>
<StackPanel Orientation="Horizontal">
<Label Width="150">Date of Birth</Label>
<DatePicker Width="200/>
</StackPanel>
</StackPanel>
Теперь вы можете добавлять, удалять, редактировать и изменять порядок в своем сердечном содержимом, не беспокоясь о столбцах и строках.
Ответ 4
Ознакомьтесь с материалом Карла.
http://web.archive.org/web/20150620104259/https://karlshifflett.wordpress.com/2008/10/23/wpf-silverlight-lob-form-layout-searching-for-a-better-solution/
Простой и чистый xaml:
<pt:Form x:Name="formMain" Style="{DynamicResource standardForm}" Grid.Row="1">
<TextBox pt:FormItem.LabelContent="_First Name" />
<TextBox pt:FormItem.LabelContent="_Last Name" />
<TextBox pt:FormItem.LabelContent="_Phone" Width="150" HorizontalAlignment="Left" />
<CheckBox pt:FormItem.LabelContent="Is _Active" />
</pt:Form>
Ответ 5
Вот библиотека для него
Пример xaml:
<UserControl ...
xmlns:autoRowGrid="http://gu.se/AutoRowGrid"
...>
<autoRowGrid:Grid ColumnDefinitions="Auto *">
<autoRowGrid:Row Name="first row">
<TextBlock Text="foo1" />
<TextBox Text="{Binding Value1}" />
</autoRowGrid:Row>
<autoRowGrid:Row Name="second row">
<TextBlock Text="foo2" />
<TextBox Text="{Binding Value2}" />
</autoRowGrid:Row>
</autoRowGrid:Grid>
...
Это расширение разметки, которое возвращает ванильный WPF Grid
для красивого неглубокого визуального дерева.
![NuGet]()
Ответ 6
Если вы согласитесь, я рекомендую Expression Blend, если вы собираетесь делать много дизайна пользовательского интерфейса. Это позволяет упростить просмотр элементов. Управление вложением в различные контейнеры - хороший способ заставить динамический интерфейс, но структурирован.
Обычно я использую панель Grid, чтобы разбить окно на функциональные области. Затем я буду использовать серию StackPanels (часто вертикальную стеклянную панель с горизонтальными StackPanels внутри нее, каждая с меткой и текстовым полем).
К сожалению, сетки работают только так, как вы заявили. Элементы в них указывают строку и/или столбец, в котором они находятся. Если вы использовали Blend, добавление Grid Columns или Rows будет иметь элементы управления, автоматически изменяющие спецификацию строки/столбца, чтобы оставаться в позиции, в которой они были размещены.
Надеюсь, что это поможет.
Expression Blend Trial в Microsoft.
UPDATE:
VS2012 имеет множество функций Expression Blend, запеченных в дизайнере WPF. Большая часть потребности в копии Blend больше не существует, поскольку разработчики имеют доступ к большому количеству интересных инструментов из Blend.
Ответ 7
В нашем продукте мы используем HeaderedContentControl для размещения форм в сетке. Шаблон управления имеет метку и отступы/поля, так что содержание управления всегда равномерно распределено. В XAML мы просто добавляем их в столбцы.
Я бы опубликовал некоторый XAML, но я нахожусь в середине создания нового компьютера.: | Но из того, что я помню, это выглядело бы примерно так:
<Style x:Key="hccFormStyle" Targettype="{x:Type HeaderedContentControl}>
... some setters for colors, margin, padding, etc...
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Label Content={Binding Content} Target={Binding Tag}> <-- pass the control for the access key with the tag
<ContentPresenter>
</ControlTemplate>
...triggers if necessary - hover states, etc...
</style>
Затем в сетке вы определяете свои строки и столбцы и помещаете одну из них в каждую ячейку или просто вниз по каждой строке:
<HeaderedContentControl x:Name="username" Grid.Column=0 Content="User Name" Tag=textboxUserName>
<Textbox x:Name=textboxUserName>
</HeaderedContentControl>
Я мог бы ответить на другой вопрос, но именно так мы выкладываем наши формы.
Ответ 8
У меня была та же проблема, переупорядочение элементов управления в макете на основе сетки - настоящая боль.
Итак, я написал настраиваемую панель, которая делает "форму макета" (группы из двух столбцов, все метки одинакового размера, все управляют одинаковым размером, все выровнено и т.д.), это в моем блоге: http://www.nbdtech.com/Blog/archive/2010/07/27/easy-form-layout-in-wpf-part-1-ndash-introducing-formpanel.aspx
Ответ 9
Сегодня я столкнулся с этим сообщением, имея тот же вопрос, используя ответы в этом потоке. Я придумал удобное решение для простых пар текста/текста. Чтобы добавить новые поля, просто раскройте коллекцию "FormItems".
Xmlns: C = "CLR-пространств имен: System.Collections; сборка = mscorlib"
<Window.Resources>
<c:ArrayList x:Key="FormItems">
<c:DictionaryEntry Key="First Name" Value="John"/>
<c:DictionaryEntry Key="Last Name" Value="Smith"/>
</c:ArrayList>
</Window.Resources>
<ItemsControl ItemsSource="{StaticResource FormItems}" Grid.IsSharedSizeScope="True">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="Label"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<TextBlock>
<Run Text="{Binding Key}"/><Run Text=": "/>
</TextBlock>
<TextBox Grid.Column="1" Text="{Binding Value}"/>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
![Базовый результат компоновки формы]()
Не было учета полей и отступов, он просто показывает концепцию использования DataTemplate для повторного использования макета каждого элемента. Он может быть легко адаптирован для включения других типов данных и элементов управления. Вы даже можете использовать ItemTemplateSelector для выбора другого шаблона в зависимости от типа словаряEntry.Value
ИЗМЕНИТЬ
Другой подход, который я нашел, облегчил DataBinding, заключался в том, чтобы использовать Visual Studio для создания нового WPF "Custom Control". Это создаст новый файл с именем Themes/Generic.xaml с новым стандартом по умолчанию, определенным там. Несколько простых изменений, и мы можем использовать ItemsControl для отображения нашего нового элемента управления.
Новый класс:
public class FormControlItem : ContentControl
{
public object Field {
get { return base.GetValue(FieldProperty); }
set { base.SetValue(FieldProperty, value); }
}
static FormControlItem() {
DefaultStyleKeyProperty.OverrideMetadata(
typeof(FormControlItem),
new FrameworkPropertyMetadata(typeof(FormControlItem)));
}
public static readonly DependencyProperty FieldProperty =
DependencyProperty.Register(
"Field",
typeof(object),
typeof(FormControlItem),
new FrameworkPropertyMetadata());
}
Темы /Generic.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MyApplication">
<Style TargetType="{x:Type local:FormControlItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:FormControlItem}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" SharedSizeGroup="Label"/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<ContentPresenter ContentSource="Field"/>
<ContentPresenter Grid.Column="1" ContentSource="Content"/>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
Пример использования:
<ItemsControl Grid.IsSharedSizeScope="True">
<local:FormControlItem Field="Name: ">
<TextBox Text="{Binding Path=Name}"/>
</local:FormControlItem>
<local:FormControlItem Field="Type: ">
<ComboBox
SelectedItem="{Binding Path=Type}"
ItemsSource="{Binding Path=TypeValues}"/>
</local:FormControlItem>
<local:FormControlItem Field="Category: ">
<TextBox Text="{Binding Path=Category}"/>
</local:FormControlItem>
</ItemsControl>
![Результат компоновки пользовательского контроля]()