WPF GridView: "Newspaper" Column? - wpf

I'm not sure how else to describe this, outside of calling it a "newspaper" column.
Essentially I have a potentially long list of codes that I want to display in a grid, and I have limited vertical real estate. I would like to show these codes (which are all from the same database column) in multiple columns, maybe 3-5 columns across.
I can absolutely break the data up into separate sources and bind to them separately if that is the best solution, but I thought there might be an easy, built-in way to accomplish this with WPF.

This is actually trivial using a WrapPanel.
For a hard-coded list:
<WrapPanel Orientation="Vertical">
<ItemOne />
<ItemTwo />
...
</WrapPanel>
For a data-bound list:
<ItemsControl ItemsSource="...">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate DataType="...">
...
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
If desired you can replace the ItemsControl with a ListBox or make it a ComboBox or whatever. You can use a default template for your data or use a custom template as shown above. You can even use a ListView along with a GridView if you want a multi-column list.

I suspect what you're looking at here is a custom layout panel which has a well defined height and then wraps into the next column. You could then use the ItemsPanelTemplate of the list control to use your new custom panel.
With respect to the development of the panel itself, I would suspect that either wrapping or inheriting from the Grid would be an excellent first choice. The panel could then manage the column definitions itself based on the number of items it contains.
To determine the layout of the individual items, I suspect using the ActualHeight to determine when another item would cause a column to overflow and using that to move to the next column would be the optimal solution. I would imagine using a single vertical stack panel with no border or padding inside each column may make it easier for your to offload the layout to those controls, but I believe you would still wind up having to determine which panel to lay the items out in based on the item heights.

Related

What standard WPF control should I use?

I am trying the master-detail presentation in my app: when an item in a listbox is selected, its details are displayed in an adjacent control.
This control will have a list of measurements such as height, width, weight, etc. It will also have some small graphics such as a green or red dot or a medium sized image. It will also have some rich text.
Which STANDARD WPF control should I use to contain all these elements. I am thinking of using a listbox but wonder if there are better controls to use.
My main consideration is ease of coding, then possibly efficiency of the code.
Thanks.
A listbox indicates a list of items that can be tailored using a DataTemplate for appearence. In this case you are showing the details of a selected item. I would actually use a container such as a Grid nested in your current UI and have a set of stackpanel including the details of the selected item.
<Grid>
<StackPanel>
<StackPanel Orientation="Vertical">
<TextBlock>Detail1</TextBlock>
<TextBox></TextBox>
</StackPanel>
<StackPanel Orientation="Vertical">
<TextBlock>Detail2</TextBlock>
<TextBox></TextBox>
</StackPanel>
</StackPanel>
</Grid>
This is only one suggestion but the point is to use a container and use a set of controls in the containers - textblock,textbox,checkboxes(boolean details), etc... this will allow you to use any control type necessary to represent the specific data field of the selected item.
You don't want to use a listbox unless you have a collection of similar items, and you want one or more items to be 'selected' at some point. It sounds like that is not what you want for the details part.
You do have a collection, which is shown in your master list. You should bind the SelectedItem in your master list to a property in your viewmodel. Then you can bind that same property to the details section of your UI. When the selection in the master list changes, your details UI will automatically update to reflect the changes.
<ListBox x:Name="masterList" ItemsSource="{Binding MyItems}" SelectedItem="{Binding MySelectedItem, Mode=TwoWay}"></ListBox>
<UserControl x:Name="detailsControl" DataContext="{Binding MySelectedItem}"> </UserControl >

Set DataGrid size to fit all its contents

I need to make DataGrid size to fit all its contents (even if DataGrid will be bigger than it's parent). Is it possible?
So, the answer I have found... just put DataGrid into StackPanel with vertical orientation. It has unbounded height, so the grid will take as much space as needed.
Edit: Re: Original Poster's Comment
Howdy again,
The real answer to your question is No--I'm sure you don't want to hear that. There is no way to get a child to break away and do its own thing.
However, there are patterns we can use to work around the problem. These work arounds give an effect similar to what you want. The hardest is breaking the limitations determined by the DataGrid's parent. From what I can tell, you only have two routes you can go:
Option 1: Refactor all of parents to resize with the DataGrid. The best way to do this is to use MinWidth and MinHeight properties on everything. By default they will use their size, but if one of their children needs more room, they will expand. Doing this allows the DataGrid to expand as its needs require.
<Grid MinWidth="500" MinHeight="500">
<sdk:DataGrid ItemsSource="{Binding Items}">
</Grid>
Option 2: Place your DataGrid over your "parent" controls. Think HTML/CSS. This is the trickiest concept, because you have to "know" where to put the DataGrid and how it will grow. You can add a clipping path to make the DataGrid look like it is a child of the Grid, but that is an answer to another post.
<Grid Width="500", Height="500"/>
<sdk:DataGrid ItemsSource="{Binding Items}" Margin="300,300,0,0"/>
Once again, I hope this helps. Let me know if you need anything else.
Howdy,
I'm assuming you want scrollbars on the DataGrid.
By default the DataGrid will generate all columns. But, because it doesn't enable the scrollbars by default, it tries to fit all of the columns it finds into one screen. You can enable these scrollbars by setting the DataGrid's ScrollViewer to show them.
If this isn't what you need, let me know.
Have a great day!
<sdk:DataGrid
ItemsSource="{Binding Items}"
AutoGenerateColumns="True"
ScrollViewer.HorizontalScrollBarVisibility="Visible"
ScrollViewer.VerticalScrollBarVisibility="Visible"/>
P.S. If you are setting up your columns manually, do not set Width="*". Setting Width="*" tells the DataGrid to only use the remainder width available in one screen.
Avoid this! <sdk:DataGridTextColumn ... Width="*"/>

Silverlight 4 nested ListBox controls performance issue

I am working on a silverlight page that will have a horizontal list box that will contain a list of "cards". Each "card" contains a vertical list box with some text in it. However, I am running into a lot of performance issues. Has anyone experienced any performance issues with nested listboxes in the past?
If its a DataGrid then Paging can give good performance. If its ListBox then we should keep an eye on the count of data binded with listbox.
Are you trying to bind the full list on single shot from server ? Then this will definitely affect the performance.
UI Virtualization might help you. Try to use VirtualizingStackPanel (instead of StackPanel) as the ItemsPanel of your Listbox:
<ListBox>
...
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>

Silverlight DataPager - Split Into 3X3?

I have a ListBox bound to an observable collection.
I also have a data pager bound to the itemsource of the list box.
I currently have the data pager set to only show up to 3 rows.
How would I go about changing the style ListBox style (or something else) such that I could have a 3X3 display? For example, the first three items in my observable collection would be displayed on the first row of the list box, horizontally next to each other, then the next row would contain the next three items in the observable collection?
Any info would be greatly appreciated.
Thanks.
Chris
It sounds like you want to use an ItemsControl with a WrapPanel (from the Silverlight Toolkit) in the ItemsPanelTemplate.
<ItemsControl xmlns:controls="clr-namespace:Microsoft.Windows.Controls;assembly=Microsoft.Windows.Controls">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<controls:WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
Here's a short tutorial about the WrapPanel: http://blogs.silverlight.net/blogs/justinangel/archive/2008/11/05/silverlight-toolkit-wrappanel.aspx

Resizing Listbox Contents according to Listbox dimensions

I am attempting to resize the contents of my listbox according to the listbox itself. This is being done in WPF.
Any ideas on how this might be possible?
I assume when you say "resize" you mean that you want to stretch the items in both directions. To take a default ListBox and stretch the items horizontally all you need is:
<ListBox HorizontalContentAlignment="Stretch"/>
The default is Left so all the ListBoxItems end up pushed to the left and sized individually based on their content.
Vertical stretching requires getting rid of the StackPanel used to do layout for the items because it has no concept of resizing its children in the direction of Orientation. The simplest thing to use is a UniformGrid but you might want something more custom depending on how you want the items to size relative to each other. You'll also need to do the same thing with the VerticalContentAlignment setting (Center by default). So here's one that will stretch items both ways:
<ListBox HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="1"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
</ListBox>

Resources