WPF - Как запретить столбцам псевдосетки ItemsControl танцевать / прыгать во время макета

Несколько другое вопросы в SO пришли к тому же выводу, что и я, - используя ItemsControl с DataTemplate для каждый элемент, созданный для размещения элементов таким образом, чтобы они напоминали сетку, намного проще (особенно для форматирования), чем использование ListView.

Код выглядит примерно так:

<StackPanel Grid.IsSharedSizeScope="True">
  <!-- Header -->
  <Grid>
    <Grid.ColumnDefinitions>
      <ColumnDefinition Width="Auto" SharedSizeGroup="Column1" />
      <ColumnDefinition Width="Auto" SharedSizeGroup="Column2" />
    </Grid.ColumnDefinitions>
    <TextBlock Grid.Column="0" Text="Column Header 1" />
    <TextBlock Grid.Column="1" Text="Column Header 2" />
  </Grid>
  <!-- Items -->
  <ItemsControl ItemsSource="{Binding Path=Values, Mode=OneWay}">
    <ItemsControl.ItemTemplate>
      <DataTemplate>
        <Grid>
          <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" SharedSizeGroup="Column1" />
            <ColumnDefinition Width="Auto" SharedSizeGroup="Column2" />
          </Grid.ColumnDefinitions>
          <TextBlock Grid.Column="0" Text="{Binding ColumnProperty1}" />
          <TextBlock Grid.Column="1" Text="{Binding ColumnProperty2}" />
        </Grid>
      </DataTemplate>
    </ItemsControl.ItemTemplate>
  </ItemsControl>
</StackPanel>

Проблема, которую я вижу, заключается в том, что всякий раз, когда я меняю местами объект, к которому привязан ItemsSource (это ObservableCollection, на который я заменяю ссылку, а не очищаю и добавляю заново), вся `` сетка '' танцует в течение нескольких секунд. .

Предположительно, он выполняет несколько проходов макета, чтобы все столбцы Auto-width совпадали.

Это очень отвлекает моих пользователей, и я хотел бы разобраться с этим. Кто-нибудь еще видел это?


person Drew Noakes    schedule 24.07.2009    source источник
comment
У меня точно такая же проблема. Вы когда-нибудь получали разрешение на это?   -  person Rick Glos    schedule 19.01.2011
comment
@Rick: к сожалению, нет, я так и не понял, что здесь происходит. Это стало настолько раздражающим, что я просто выбрал столбцы фиксированной ширины, хотя, конечно, это сопровождалось другим набором проблем. В моем случае это было меньшее зло.   -  person Drew Noakes    schedule 19.01.2011
comment
@Rick, ты был хостингом внутри WinForms? Было бы хорошо получить на это репортаж. Какую версию .NET вы используете? Я использовал 3.5 (до SP1).   -  person Drew Noakes    schedule 19.01.2011
comment
Я использую чистый WPF и .NET 4.0. Я использую платформу Prism и запускаю View с поддержкой ViewModel, которую я использую для хранения коллекции объектов. Как и вы, я использую комбинацию сетки, расположенной поверх ItemsControl, а затем выравниваю все столбцы сетки с SharedSizeGroup. Забавно то, что когда я издевался над данными - не видел проблем. Теперь, когда я набираю реальные числа, он просто начал танцевать / прыгать.   -  person Rick Glos    schedule 19.01.2011
comment
Извините, я не могу помочь с вашей проблемой, но ваш код XAML спас положение! Я не мог понять, как заставить Grid правильно работать с ItemsControl, поэтому спасибо :)   -  person GONeale    schedule 05.07.2012
comment
Используя ответ Дэвида. Я установил свойство MinWidth, и все решилось само.   -  person Ryan Amies    schedule 02.09.2014


Ответы (4)


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

Простые текстовые блоки, показанные в OP, вероятно, не так легко проявляют проблему, потому что они статичны. Если вы добавляете TextBox (не TextBlock) в ячейку, а затем во время выполнения введите достаточно текста, чтобы TextBox автоматически расширял ячейку, вы должны сразу увидеть, как он начинает дико танцевать .. .. это далеко за гранью «слишком много, чтобы быть приемлемым». В моем ItemsControl было 7 строк.

Это эффективно превращает широко разрекламированный подход IsSharedSizeScope + ItemsControl в полный запрет, особенно для редактируемого содержимого Grid, ориентированного на TextBox.

Для моих нужд подход ListView или, скорее, «ItemsControl + GridViewRowPresenter», представленный здесь и здесь является очень прямой альтернативой и не имеет любая из этих проблем с компоновкой.

Для тех, кто спрашивает «почему не DataGrid?»: DataGrid требует определенного подхода к редактированию. Я был готов проработать все это, но зашел в тупик из-за того, как DataGrid искажает поддержку Validation.Error. Маленькие красные поля ошибок валидации будут работать нормально для простых столбцов DataGridTextColumn, но для столбцов DataGridTemplateColumns (необходимых для предоставления более одного текстового поля в одном столбце) сначала будут отображаться красные поля, а затем непоследовательно скрывать их в зависимости от того, где вы случайно щелкнули мышью. DataGrid. При последующих обновлениях валидации они будут полностью невидимы. (старый пример: http://code.google.com/p/itraacv2-1/source/browse/trunk/scraps/tabSponsor%20-%20before%20deactive%20rewrite.xaml, выполните поиск до" nugget: for чертова жизнь меня "...)

Весь мой исходный код проекта находится в сети. Этот подход GridViewRowPresenter представлен здесь: http://code.google.com/p/itraacv2-1/source/browse/trunk/App/View/tabSponsor.xaml

person Beej    schedule 24.06.2011

Попробуйте установить MinWidth для всех столбцов вашей сетки.

Я тоже испытал эту нервную нестабильность. Однако я взял его под контроль, указав установленную MinWidth для всех столбцов моей сетки. Кажется, что это стабилизирует ситуацию при первом отображении экрана. Конечно, поскольку ваши столбцы все еще связаны, они увеличиваются до максимальной ширины любого элемента управления.

Кроме того, выключите IsSharedSizeScope и попробуйте сначала выровнять сетки, а затем снова включите его.

person David    schedule 26.11.2013
comment
Можете ли вы установить MinWidth на что-нибудь очень маленькое, чтобы не тратить лишнюю ширину? - person Drew Noakes; 02.09.2014

К сожалению, мне не удалось воспроизвести проблему с предоставленным кодом. Я пробовал менять местами образцы от 20 до 1000 элементов и 100 разной ширины внутри коллекции. Ничего не танцевало. В огромных коллекциях (200 и выше) пользовательский интерфейс некоторое время зависал, а затем выпускался, показывая новую сетку с предоставленными элементами.

person archimed7592    schedule 22.11.2009
comment
@Archimed, спасибо, что попробовали. Я видел, как это происходило в нескольких разных местах моего пользовательского интерфейса всего с 5 строками, и мне приходилось использовать столбцы фиксированной ширины без IsSharedSizeScope, чтобы избежать покачивания. Интересно, связано ли это с размещением моих элементов в WinForms ElementHosts ... - person Drew Noakes; 25.11.2009

У меня была такая же проблема, я попытался установить MinWidth, как предложено в одном из ответов, но у меня это не сработало. Что действительно помогло, так это привязка ширины одной сетки к другой. Я оставил некоторые столбцы с SharedSizeGroup, и ничего не скачет:

<Grid Grid.IsSharedSizeScope="True">
...
    <Grid Grid.Row="1">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" SharedSizeGroup="Group0"/>
            <ColumnDefinition Width="Auto" SharedSizeGroup="Group1"/>
            <ColumnDefinition Width="Auto" SharedSizeGroup="Group2"/>
            <ColumnDefinition Width="Auto" x:Name="Column3"/>
            <ColumnDefinition Width="Auto" x:Name="Column4"/>
            <ColumnDefinition Width="Auto" x:Name="Column5"/>
        </Grid.ColumnDefinitions>
    ...
    </Grid>

    <ItemsControl>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto" SharedSizeGroup="Group0"/>
                        <ColumnDefinition Width="Auto" SharedSizeGroup="Group1"/>
                        <ColumnDefinition Width="Auto" SharedSizeGroup="Group2"/>
                        <ColumnDefinition Width="{Binding Path=ActualWidth, ElementName=Column3}"/>
                        <ColumnDefinition Width="{Binding Path=ActualWidth, ElementName=Column4}"/>
                        <ColumnDefinition Width="{Binding Path=ActualWidth, ElementName=Column5}"/>
                    </Grid.ColumnDefinitions>
                </Grid>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
...
</Grid>

Я не знаю, сколько столбцов вы можете оставить с помощью SharedGroupSize и сколько из них нужно связать, поэтому вы можете поиграть со столбцами, чтобы увидеть, что работает для вас.

person Andreas Koder    schedule 04.11.2015