Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF - How to stop an ItemsControl pseudo-grid's columns from dancing/jumping around during layout

Several other questions on SO have come to the same conclusion I have -- using an ItemsControl with a DataTemplate for each item constructed to position items such that they resemble a grid is much simpler (especially to format) than using a ListView.

The code resembles:

<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>

The problem I'm seeing is that whenever I swap the object to which the ItemsSource is bound (it's an ObservableCollection that I replace the reference to, rather than clear and re-add), the entire 'grid' dances about for a few seconds.

Presumably it is making a few layout passes to get all the Auto-width columns to match up.

This is very distracting for my users and I'd like to get it sorted out. Has anyone else seen this?

like image 262
Drew Noakes Avatar asked Nov 06 '22 20:11

Drew Noakes


2 Answers

It seems the grid's content must be a certain level of complexity before this problem is visible.

Simple TextBlock's as shown in the OP probably don't manifest the problem quite as readily because they're static size. If you throw a TextBox (not TextBlock) in a cell, then at run-time, enter enough text to cause the TextBox to auto expand the cell, you should see it start dancing wildly right away... it's well over the too-much-to-be-acceptable line. I had 7 rows in my ItemsControl.

This effectively renders the much promoted IsSharedSizeScope + ItemsControl approach to be a complete no-go, specifically for editable, TextBox oriented Grid content.

For my needs, the ListView or rather "ItemsControl + GridViewRowPresenter" approach as presented here and here is a very direct alternative and does not have any of these layout issues.

For those asking "why not a DataGrid?": the DataGrid imposes a certain approach to editing. I was willing to work through all that but wound up at a dead end with how the DataGrid mangles Validation.Error support. The little red Validation Error boxes would work fine for simple DataGridTextColumn's but for DataGridTemplateColumns (necessary to provide more than a single TextBox in one column), it would initially show the red boxes and then inconsistently hide them based on where you happened to click around the DataGrid. Upon subsequent Validation refreshes they would be completely invisible. (old example: http://code.google.com/p/itraacv2-1/source/browse/trunk/scraps/tabSponsor%20-%20before%20deactive%20rewrite.xaml, search down to "nugget: for the friggin life of me" ...)

My entire project source is online. This GridViewRowPresenter approach is represented here: http://code.google.com/p/itraacv2-1/source/browse/trunk/App/View/tabSponsor.xaml

like image 200
Beej Avatar answered Dec 19 '22 14:12

Beej


Try set MinWidth on all your grid columns.

I have also experienced this jumpy instability. However, I got it under control by specifying a set MinWidth on all my grid columns. This seems to stabilize things when the screen is first displayed. Of course, because your columns are still linked, they grow to the max width of whatever control wins.

Also, switch off IsSharedSizeScope and try to get your grids to line up first, then switch it back on.

like image 45
David Avatar answered Dec 19 '22 16:12

David