Я нашел и ответ, который, по-видимому, имеет несколько преимуществ в плане улучшения читаемости и удобства сопровождения XAML.
Создав ControlTemplates для TextBox и Combobox, вы можете легко установить сетку с SharedSizeGroup на столбцы, что помогает поддерживать одинаковую ширину надписей. Созданный шаблон элемента управления использует свойство Tag элемента управления Logical для определения текста для метки в визуальном элементе, созданном шаблоном.
Рассмотрим следующий XAML, который создает два текстовых поля, оба привязаны к данным для базового бизнес-объекта:
<WrapPanel Orientation="Horizontal" Grid.IsSharedSizeScope="True">
<TextBox Tag="On Hand:"
Text="{Binding Path=Product.StockOnHand}"
Template="{StaticResource LabeledTextBoxTemplate}"
IsReadOnly="True"
ToolTip="" />
<TextBox Tag="On Order:"
Text="{Binding Path=Product.StockOnOrder}"
Template="{StaticResource LabeledTextBoxTemplate}"
IsReadOnly="True"
ToolTip="" />
</WrapPanel>
Коробки находятся внутри панели переноса, где SharedSizeGroup имеет значение true. Это позволяет сеткам (которые создают шаблоны элементов управления) обмениваться информацией о ширине столбца. Поскольку текстовые поля находятся внутри WrapPanel, они будут использовать как можно большую ширину перед переносом на следующую строку.
Шаблон ControlTemplate (и стиль), который отображает вышеупомянутые логические текстовые поля в сетки, где каждая сетка имеет два столбца, один из которых содержит метку, а другой содержит текстовое поле, выглядит следующим образом:
<!--Style and ControlTemplates to support aligned, labeled text boxes and combo boxes.-->
<Style TargetType="Grid"
x:Key="LabelledDataGridStyle">
<Setter Property="Margin"
Value="0,0,12,4" />
</Style>
<Style TargetType="ColumnDefinition"
x:Key="LabelingGridThirdColumnStyle">
<Setter Property="Width"
Value="150" />
<Style.Triggers>
<DataTrigger Binding="{Binding Path=ItemWidth,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=WrapPanel,AncestorLevel=1}}"
Value="{x:Null}">
<Setter Property="Width"
Value="Auto" />
<Setter Property="SharedSizeGroup"
Value="C" />
</DataTrigger>
</Style.Triggers>
</Style>
<ControlTemplate TargetType="TextBox" x:Key="LabeledTextBoxTemplate">
<Grid Style="{StaticResource LabelledDataGridStyle}">
<Grid.ColumnDefinitions>
<ColumnDefinition SharedSizeGroup="A" Width="Auto" />
<ColumnDefinition Style="{StaticResource LabelingGridThirdColumnStyle}" />
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Path=Tag,RelativeSource={RelativeSource TemplatedParent}}"
VerticalAlignment="Top"
Margin="0,4,8,0"
HorizontalAlignment="Left" />
<TextBox Text="{Binding Path=Text,RelativeSource={RelativeSource TemplatedParent}}"
TextAlignment="{Binding Path=TextAlignment,RelativeSource={RelativeSource TemplatedParent}}"
Style="{Binding Path=Style,RelativeSource={RelativeSource TemplatedParent}}"
Background="{Binding Path=Background,RelativeSource={RelativeSource TemplatedParent}}"
ToolTip="{Binding Path=ToolTip,RelativeSource={RelativeSource TemplatedParent}}"
ContextMenu="{Binding Path=ContextMenu,RelativeSource={RelativeSource TemplatedParent}}"
MinWidth="100"
Grid.Column="1" />
</Grid>
</ControlTemplate>
Он не идеален (элемент управления Panel, выполняющий эту работу, был бы идеальным), но для быстрого исправления это прекрасно работает.