Используя Сетку как ItemsPanel для ItemsControl в Silverlight 3

Это возможный сделать что-то вроде этого:

    <ListBox>
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <Grid />
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBox Text="{Binding Text}" Grid.Column="{Binding Column}" Grid.Row="{Binding Row}"  />
            </DataTemplate>                
        </ListBox.ItemTemplate>
    </ListBox>

Источник объектов был бы чем-то как Список объектов, которые имели текст, свойства Column и Row.

Действительно ли это возможно? Я действительно хочу иметь свою сетку данных быть связанными данными.

11
задан AnthonyWJones 6 March 2010 в 15:53
поделиться

3 ответа

То, что у вас есть, не будет работать, потому что Silverlight оборачивает каждый элемент - каждый экземпляр DataTemplate - в ListBoxItem, и присоединенные свойства Grid.Column и Grid.Row необходимо применять к этому ListBoxItem, а не к TextBox, который становится содержимым этого ListBoxItem.

Хорошей новостью является то, что вы можете устанавливать атрибуты для неявного ListBoxItem с помощью ListBox.ItemContainerStyle.

Плохая новость в том, что ItemContainerStyle не поддерживает привязку. Таким образом, вы не можете использовать его для установки присоединенных свойств Grid.Column и Grid.Row к атрибутам текущего элемента данных.

Одно из решений, которое я использовал, - создать подкласс ListBox и настроить привязку в PrepareContainerForItemOverride. Вот очень грубый, зашитый пример:

public class GriderrificBox : ListBox
{
  protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
  {
    base.PrepareContainerForItemOverride(element, item);

    FrameworkElement fe = element as FrameworkElement;
    if (fe != null)
    {
      BindingOperations.SetBinding(fe, Grid.RowProperty,
        new Binding { Source = item, Path = new PropertyPath("Row") });
      BindingOperations.SetBinding(fe, Grid.ColumnProperty,
        new Binding { Source = item, Path = new PropertyPath("Column") });
    }
  }
}

Использование:

<local:GriderrificBox>
  <ListBox.ItemTemplate>
    <DataTemplate>
      <TextBox Text="{Binding Text}" />
    </DataTemplate>
  </ListBox.ItemTemplate>
  <ListBox.ItemsPanel>
    <ItemsPanelTemplate>
      <Grid />
    </ItemsPanelTemplate>
  </ListBox.ItemsPanel>
</local:GriderrificBox>

В этом коде есть (по крайней мере) два основных недостатка: во-первых, вам все равно нужно явно указать ItemsPanel в XAML, хотя элемент управления работает только с панелями Grid. ; и, во-вторых, пути привязки жестко встроены в код. К первому можно обратиться, используя стандартный механизм стиля управления по умолчанию, а ко второму - путем определения таких свойств, как RowBindingPath и ColumnBindingPath, с которыми PrepareItemForContainerOverride может обращаться вместо использования жестких путей. Надеюсь, хватит, чтобы вы все равно начали!

3
ответ дан 3 December 2019 в 10:44
поделиться

Сетка просто не подходит для использования, которое вы пытаетесь здесь разместить. Ожидается, что набор доступных строк и столбцов будет определен заранее, прежде чем вы начнете назначать элементы ячейкам.

Если вы пытаетесь создать список, который использует как горизонтальное, так и вертикальное пространство, возможно, лучше всего подойдет WrapPanel из Silverlight Toolkit.

С другой стороны, если вы пытаетесь создать «сетку данных», рассмотрите возможность транспонирования или группировки столбцов в каждой строке модели, тогда вы можете использовать DataGrid вместо ListBox

2
ответ дан 3 December 2019 в 10:44
поделиться

Если вы заинтересованы в поддержке такого сценария в будущей версии Silverlight, пожалуйста, проголосуйте за перенос макета Adobe Flex Grid , который будет отлично работают в таком сценарии

0
ответ дан 3 December 2019 в 10:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: