64387

wpf using grid as itemshost stacking multiple items in single 'cell' automatically

Question:

I am binding an items control to a datasource and using a grid as my itemshost. I wish to have the items locate themselves into the correct cell in the grid (I can do this), and also stack themselves so they are not all on top of each other (I can't figure out how to insert the items into a stackpanel or other panel in the grid).

here is the .cs file for the two classes:

public class listofdata { public List<data> stuff { get; set; } public listofdata() { stuff = new List<data>(); stuff.Add(new data(0, 0, "zeroa")); stuff.Add(new data(0, 0, "zerob")); stuff.Add(new data(1, 0, "onea")); stuff.Add(new data(1, 0, "oneb")); stuff.Add(new data(1, 1, "twoa")); stuff.Add(new data(1, 1, "twob")); } } public class data { public int x { set; get; } public int y { set; get; } public string text { get; set; } public data(int x, int y, string text) { this.x = x; this.y = y; this.text = text; } } }

Here is my XAML

<Window x:Class="GridTester.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:src="clr-namespace:GridTester" xmlns:sys="clr-namespace:System;assembly=mscorlib" Title="MainWindow" > <Window.Resources> <DataTemplate DataType="{x:Type src:data}"> <Button Content="{Binding text}"/> </DataTemplate> <src:listofdata x:Key="MyDataSource"> </src:listofdata> </Window.Resources> <ListBox Name="Main" ItemsSource="{Binding Source={StaticResource MyDataSource},Path=stuff}"> <ListBox.ItemsPanel> <ItemsPanelTemplate> <Grid Name="MyGrid"> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition /> <RowDefinition /> </Grid.RowDefinitions> </Grid> </ItemsPanelTemplate> </ListBox.ItemsPanel> <ListBox.ItemContainerStyle> <Style> <Setter Property="Grid.Column" Value="{Binding x}"/> <Setter Property="Grid.Row" Value="{Binding y}"/> </Style> </ListBox.ItemContainerStyle> </ListBox> </Window>

My problem is that all the buttons ending with 'a' are under the buttons ending in b. I can't see how to use XAML to insert the items into a dynamically created stackpanel

I tried to create a class derived from Grid, thinking to intercept the addition of the children to add stackpanels myself and then move the children from the grid to the stackpanels, but attempting to manipulate the children in an itemshost causes an exception to be thrown.

Ultimately I just want the items in my datasource to be able to bind to a 'cell' in the grid, and if multiple items bind to the same cell, I want them to stack.

Answer1:

You could do this at the data level like HighCore suggested, but since the current data structure already contains the necessary information, it should be possible for the ItemsControl to handle it. Consider adding a <a href="http://msdn.microsoft.com/en-us/library/system.windows.data.propertygroupdescription.aspx" rel="nofollow">group description</a> to the ListBox's item collection, and use a <a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.groupstyle.aspx" rel="nofollow">GroupStyle</a> whose <a href="http://msdn.microsoft.com/en-us/library/system.windows.controls.groupstyle.panel.aspx" rel="nofollow">Panel</a> is a StackPanel.

Answer2:

Here is the solution using the hints from nmclean (Thanks so much) This section establishes the grouping which will be used to distribute the elements around the grid.

<CollectionViewSource Source="{Binding Source={StaticResource MyDataSource}}" x:Key="cvs"> <CollectionViewSource.GroupDescriptions> <PropertyGroupDescription PropertyName="ordinal"/> </CollectionViewSource.GroupDescriptions> </CollectionViewSource>

this section is the main listbox bound to the data in the collectionviewsource, The containerstyle contains the bindings to put the groupitem into the correct cells in the grid. The grid is in the groupstyle.panel

<ListBox ItemsSource ="{Binding Source={StaticResource cvs}}" > <ListBox.GroupStyle> <GroupStyle> <GroupStyle.ContainerStyle> <Style TargetType="{x:Type GroupItem}"> <Setter Property="Grid.Row" Value="{Binding Items[0].y,diag:PresentationTraceSources.TraceLevel=High}" /> <Setter Property="Grid.Column" Value="{Binding Items[0].x,diag:PresentationTraceSources.TraceLevel=High}" /> </Style> </GroupStyle.ContainerStyle> <GroupStyle.Panel> <ItemsPanelTemplate> <Grid> <Grid.RowDefinitions> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition></ColumnDefinition> <ColumnDefinition></ColumnDefinition> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> </Grid> </ItemsPanelTemplate> </GroupStyle.Panel> </GroupStyle> </ListBox.GroupStyle>

Here is the total solution in case you need it:

<Window x:Class="GridTester.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:diag="clr-namespace:System.Diagnostics;assembly=WindowsBase" xmlns:src="clr-namespace:GridTester" xmlns:sys="clr-namespace:System;assembly=mscorlib" Title="Window1" Height="300" Width="300" Name="TOPWindow"> <Window.Resources> <DataTemplate DataType="{x:Type src:data}"> <Button Content="{Binding text}"/> </DataTemplate> <src:listofdata x:Key="MyDataSource"></src:listofdata> <CollectionViewSource Source="{Binding Source={StaticResource MyDataSource}}" x:Key="cvs"> <CollectionViewSource.GroupDescriptions> <PropertyGroupDescription PropertyName="ordinal"/> </CollectionViewSource.GroupDescriptions> </CollectionViewSource> </Window.Resources> <ListBox ItemsSource ="{Binding Source={StaticResource cvs}}" > <ListBox.GroupStyle> <GroupStyle> <GroupStyle.ContainerStyle> <Style TargetType="{x:Type GroupItem}"> <Setter Property="Grid.Row" Value="{Binding Items[0].y,diag:PresentationTraceSources.TraceLevel=High}" /> <Setter Property="Grid.Column" Value="{Binding Items[0].x,diag:PresentationTraceSources.TraceLevel=High}" /> </Style> </GroupStyle.ContainerStyle> <GroupStyle.Panel> <ItemsPanelTemplate> <Grid> <Grid.RowDefinitions> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> <RowDefinition></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition></ColumnDefinition> <ColumnDefinition></ColumnDefinition> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> </Grid> </ItemsPanelTemplate> </GroupStyle.Panel> </GroupStyle> </ListBox.GroupStyle> </ListBox> </Window>

The code file looks like this now:

public class listofdata : List<data> { public listofdata() { Add(new data(0, 0, "zeroa")); Add(new data(0, 0, "zerob")); Add(new data(1, 0, "onea")); Add(new data(1, 0, "oneb")); Add(new data(1, 1, "twoa")); Add(new data(1, 1, "twob")); } } public class data { public int x { set; get; } public int y { set; get; } public int ordinal { get { return x * 1000 + y; } } public string text { get; set; } public data(int x, int y, string text) { this.x = x; this.y = y; this.text = text; } }

Recommend

  • Can't get my svg image displayed in Firefox?
  • Microsoft Visual Studio Credential Errors on Microsoft Azure Account
  • Does Python have something like Perl 5.10's “state” variables?
  • Update references to a submodule in parent repository after submodule's git history is re-writt
  • Proguard returned with error code 1, error can't find referenced class android.support.v4.app
  • How to change type datatable column [duplicate]
  • Error sending text message Android
  • Is there a generic TableModel we can use in JTables?
  • std::future returned from std::async hangs while going out of scope
  • Is it possible to use pseudo-elements to make containing elements wrap around an absolutely-position
  • Stop or Detection dll injection loadlibrary
  • matplotlib and transparency figure
  • RSRuntimeException: Loading of ScriptC script failed (build tools 19.0.2)
  • Overlaying text on video with required angle using FFMPEG
  • Comparing a large set of images by content
  • flexbox sticky footer
  • Appending spaces with str_pad
  • C# mvc3 redirect sitemap.xml to controller action
  • Preloading webView doesn't work - trying to reduce loading time
  • Google Geocoding API limit exceeded on cell network, but not on wifi
  • How to set http status code when responding to servlet client from Filter class-method in tomcat
  • Slick: How can I combine a SQL LIKE statement with a SQL IN statement
  • Auto send email based on the time and email address in database
  • Firestore: Version history of documents
  • What are advantages/disadvantages of using Selenium for Java vs .NET applications?
  • flex tree gets chopped even after using scroll bar
  • Stop an element moving with padding on hover
  • ASP.NET MVC 2 actions for the same route?
  • Neo4j…how to get a visual representation of my data?
  • Python 3x- Compression Makes File Bigger :(
  • How to clear a browser cache in Protractor
  • How to use Streams api peek() function and make it work?
  • Stacked bar chart with continuous time-axis as x-axis
  • How to decleare char *const argv[] in swift [duplicate]
  • Bad automatic Triangulation with Mayavi for coloring a surface known only by its corner
  • How to get rgb from transparent pixel in js
  • Sign a Pdf using custom digital signature in Java
  • WPF custom control and direct content support