views:

62

answers:

1

Hi,

I have a listbox in which I am displaying the records from the database. Its coming one after the other in a single column. How to put the records programitically as 3 rows and 3 columns i.e. 3 records in a row, after that 3 records in a row. Kindly suggest?

Thanks.

+1  A: 

If the records are (or can be) a fixed width, it is easy: Just change your ListBox.ItemsPanel to a WrapPanel and set the ListBox width to be just over 3x the width of the items:

<DataTemplate DataType="{x:Type my:CustomItem}">
  <Border Width="100" ...>
    ...
  </Border>
</DataTemplate>

...

<ListBox ... Width="320">
  <ListBox.ItemsPanel>
    <ItemsPanelTemplate>
      <WrapPanel/>
    </ItemsPanelTemplate>
  </ListBox.ItemsPanel>
  ...
</ListBox>

If you need to divide the available width by three and you know that all of your items are exactly the same height (or if you are ok with all your rows being the max height of any item), there is a very simple solution using UniformGrid with no Height specified:

<ListBox ... >
  <ListBox.ItemsPanel>
    <ItemsPanelTemplate>
      <UniformGrid Width="3" />
    </ItemsPanelTemplate>
  </ListBox.ItemsPanel>
  ...
</ListBox>

If you want to divide the available width by 3 to get the item width but stack the items as closely as possible vertically, it is possible but tricky in pure XAML. (I wouldn't recommend doing it in pure XAML but if you want to do it that way, you can create a hidden Grid with three star-sized columns and a fixed-width column, then use a binding to the ActualWidth of the first column of the hidden grid.)

An easier way is to create a simple custom panel that acts like UniformGrid horizontally but StackPanel vertically. This is a very simple Panel subclass:

  • MeasureOverride computes desired width as 3* max width of any child
  • MeasureOverride computes desired height as sum(max(height of each group of 3))
  • ArrangeOverride lays out children 3 per row, each DesiredWidth/3 to the right of the previous one, and the next row being max(height) down from the current row

Obviously if you design a custom panel you wouldn't hard-code the "3" - you would make it a property, probably a DependencyProperty, so you can easily change it and so that you can reuse your panel elsewhere if need be.

Ray Burns
@Ray.Here is my Listbox itemtemplate<ListBox.ItemTemplate><DataTemplate><StackPanel><CheckBox Style="{DynamicResource CheckBox_DA}" IsChecked="{Binding IsSelected}" Content="{Binding Item.ActivityName}"/><Label Content="{Binding Item.ActivityName}" HorizontalContentAlignment="Center" FontSize="20"></Label></StackPanel></DataTemplate> </ListBox.ItemTemplate>What i need to change here to achieve the above. Kindly Suggest?Thanks
Tarun
I think any of my suggestions would apply to that ItemTemplate: You could make it fixed-width or you could divide the available width up. The height will stay pretty much the same unless something wraps, so the UniformGrid solution might work well too. It really all boils down to what you want to happen as the window size changes, etc.
Ray Burns
@Ray. Will try it out.Thanks
Tarun
@Ray. When i tried to apply ur suggestion in my existing ListBox ItemTemplate,I got the following error.'Set property 'System.Windows.Controls.ItemsControl.ItemsPanel' threw an exception.'Kindly Suggest?Thanks
Tarun
You say you applied my suggestion "in my ... ItemTemplate" which confuses me since none of my code sets the ItemTemplate property. I think that is probably your problem: ItemsPanel should be set on the ListBox directly, not in the ItemTemplate. But I'm not sure of this since I don't recognize the error you are getting. If this guess doesn't fix it, post your actual code so I can have a look at it.
Ray Burns
@Ray. Got it. Thanks
Tarun