Какие есть варианты, чтобы составить список элементов управления с пометкой в ​​Silverlight / WPF? - PullRequest
2 голосов
/ 11 августа 2010

У меня много XAML, который находится в полном беспорядке, и это обычно из-за одной вещи.GRID, Grid.Column и Grid.Row сумасшествие !!

Теперь есть несколько распространенных способов создания списков с метками в XAML:.

с помощью

Преимущества: Автоматическое изменение ширины столбцов и строк
Недостатки: Нет простого способа вставить строки / столбцы в VS или Blend [STILL !!], возможно, грязный XAML, если вы не будете осторожны, тонны прикрепленных свойств, поля должны быть установлены для каждого элемента управления, сетка предназначена для всего и определенно не предназначена для этой цели!

Да, я знаю, что естьудобные инструменты для вставки строк и столбцов без необходимости перенумерации всех полей, например XAML Powertools (см. video ).Но это все еще неуклюже, на мой взгляд (несмотря на то, что спасает жизнь в то же время.)это то, чем я всегда пользуюсь)

Преимущества: Очень легко переупорядочивать товары, относительно чистый XAML
Недостатки: Нужно знать ширинустолбец метки и установить его на каждом элементе, все равно нужно возиться с полями

<StackPanel>

    <!-- Name -->
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="Name:" Width="60" VerticalAlignment="Center" TextAlignment="Right"/>
        <TextBox Name="txtName" Width="100" Margin="5,5,0,0"/>
    </StackPanel>

    <!-- Address -->
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="Address:" Width="60" VerticalAlignment="Center" TextAlignment="Right"/>
        <TextBox Name="txtAddress" Grid.Row="1" Grid.Column="1" Width="100" Margin="5,5,0,0"/>
    </StackPanel>

</StackPanel>

с DataForm

Преимущества: Обрабатывает редактирование, различные виды для разных состояний редактирования и т. Д.
Недостатки: Все еще в предварительном просмотре полоса качества, слишком большая для большей части времени, вам нужен простой список элементов

            <dataform:DataForm x:Name="dataForm" Width="350" ItemsSource="{Binding}" HorizontalAlignment="Left" MaxWidth="500" Margin="4" Grid.Column="1"/>

См. http://www.silverlightshow.net/items/Creating-Rich-Data-Forms-in-Silverlight-3-Customization.aspx


Что я хочу!

Мне бы хотелось, чтобы какая-то сетка работала в Blendно позволяет мне легко задавать текст метки с помощью прикрепленного свойства - или каков «лучший» способ XAML.Было бы здорово учесть несколько столбцов, но, вероятно, намного сложнее.

Преимущества: Легко переупорядочивать элементы, очищать XAML, устанавливать 'cellpadding' в одном месте
Недостатки: Пока нет!

<LabelledGrid CellPadding="5" LabelStyle="{StaticResource labelStyle}>

   <TextBox LabelledGrid.Label="Name" Name="txtName" />
   <TextBox LabelledGrid.Label="Address" Name="txtAddress" />

</LabelledGrid>

или, может быть,

    <LabelledGrid CellPadding="5" LabelStyle="{StaticResource labelStyle}>

    <LabelledGrid.GridItem>
        <LabelledGrid.Label>
            Name:
        </LabelledGrid.Label>
        <TextBox Name="txtName" />
    </LabelledGrid.GridItem>

    <LabelledGrid.GridItem>
        <LabelledGrid.Label>
            Address:
        </LabelledGrid.Label>
        <TextBox Name="txtAddress" />
    </LabelledGrid.GridItem>

</LabelledGrid>

Существуют ли какие-либо элементы управления, например, как я описываю LabelledGrid - или как мне создать

Ответы [ 3 ]

2 голосов
/ 11 августа 2010

Вот как я с этим справляюсь: я создаю коллекцию из Field объектов в моей модели представления, каждый из которых предоставляет свойства Label и Value. Затем я делаю это:

<DataTemplate DataType="{x:Type local:Field}">
   <Grid>
      <Grid.ColumnDefinitions>
         <ColumnDefinition SharedSizeGroup="Label"/>
         <ColumnDefinition SharedSizeGroup="Value"/>
      </Grid.ColumnDefinitions>
      <Label Content="{Binding Label}"/>
      <TextBox Grid.Column="1" Text="{Binding Value, Mode=TwoWay}"/>
   </Grid>
</DataTemplate>

<ItemsControl Grid.IsSharedSizeScope="True" ItemsSource="{Binding FieldCollection}"/>

Это полностью устраняет проблемы упорядочения полей из XAML; поля отображаются в том порядке, в котором вы добавили их к FieldCollection. Этот подход не дает вам детального контроля над форматированием отдельных полей, и вы не можете поддерживать метки в XAML (не делая ничего хитрого), но если это не то, что вам нужно, это действительно упрощает проблему .

1 голос
/ 18 августа 2010

После прочтения статьи доктора WPF " 'I' for Item Container " я решил попробовать. Это все еще грубо, но я думаю, что это отвечает всем требованиям, и, возможно, кто-то, кто знает больше WPF, чем я, мог бы улучшить его.

В вашем Window.Resources или App.Resources добавьте следующее:

<Style x:Key="NamedControls" TargetType="{x:Type ListBox}">
  <Setter Property="BorderThickness" Value="0"/>
  <Setter Property="Grid.IsSharedSizeScope" Value="True"/>
  <Setter Property="ItemContainerStyle">
    <Setter.Value>
      <Style TargetType="{x:Type ListBoxItem}">
        <Setter Property="Focusable" Value="False"/>
        <Setter Property="Template">
          <Setter.Value>
            <ControlTemplate TargetType="{x:Type ListBoxItem}">
              <Grid>
                <Grid.ColumnDefinitions>
                  <ColumnDefinition SharedSizeGroup="NamedControls" Width="Auto"/>
                  <ColumnDefinition/>
                </Grid.ColumnDefinitions>
                <Label Content="{Binding Tag}" Padding="5 3"/>
                <ContentPresenter Grid.Column="1"/>
              </Grid>
            </ControlTemplate>
          </Setter.Value>
        </Setter>
      </Style>
    </Setter.Value>
  </Setter>
</Style>

Это отвратительно, но вам это нужно только один раз. Затем, когда вам нужно имя / контрольная группа, просто сделайте это:

<ListBox Style="{StaticResource NamedControls}">
  <TextBox Tag="Name:"/>
  <TextBox Tag="Address:"/>
  <TextBox Tag="City:"/>
</ListBox>

Он автоматически показывает тег слева от каждого элемента управления и выравнивает элементы управления вверх, даже если метки имеют разную длину.

Некоторые заметки:

  • Да, это действительно должен быть ItemsControl вместо ListBox - но если вы поместите <TextBox/> внутри ItemsControl, он станет дочерним элементом управления ItemsControl, поэтому эта техника стилей больше не работает. Мне нужно, чтобы он был элементом коллекции Items. ListBox не имеет этой проблемы; все, что вы помещаете внутрь, автоматически добавляется в Items после помещения в ListBoxItem, который затем можно соответствующим образом оформить.
  • Существует 1-пиксельное поле вокруг всей группы элементов управления (возможно, из-за чего-то в шаблоне ListBox). Мне удалось отключить границу ListBox и не дать ей сфокусироваться, но я не уверен, что делать с этим полем.
  • На самом деле все это нужно обернуть в свой собственный потомок ItemsControl (который исправит все проблемы из шаблона ListBox), но я не знаю достаточно о пользовательских элементах управления и стилях по умолчанию, чтобы запустить его. Это также позволит вам определить прикрепленное свойство для метки вместо использования тега.
1 голос
/ 11 августа 2010

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

<ControlTemplate TargetType="{x:Type TextBox}" x:Key="LabeledTextBox">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100"/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>

        <TextBlock Text="{TemplateBinding Tag}" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="5,0"/>

        <Border x:Name="Bd" Grid.Column="1" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="true">
            <ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
        </Border>
    </Grid>
    <ControlTemplate.Triggers>
        <Trigger Property="IsEnabled" Value="false">
            <Setter Property="Background" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"/>
            <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>

Теперь вы можете просто поместить свои текстовые поля в StackPanel:

<StackPanel>
    <TextBox Template="{StaticResource LabeledTextBox}" Tag="Name"/>
    <TextBox Template="{StaticResource LabeledTextBox}" Tag="Title"/>
    <TextBox Template="{StaticResource LabeledTextBox}" Tag="Description"/>
</StackPanel>

Если вы хотите более настраиваемое решение, вы можете использовать HeaderedContentControl с аналогичным шаблоном, который использует свойство Header вместо Tag и имеет ContentPresenter вместо PART_ContentHost ScrollViewer. Использование этого было бы больше похоже на то, что показывает ваш пример GridItem, где каждый элемент объявляет TextBox в качестве своего содержимого. Вы также можете использовать DataTemplates и нетекстовое содержимое, как для меток.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...