wpf usando grid como itemshost apilando múltiples elementos en una sola ''celda'' automáticamente
listboxitem wpf (2)
Aquí está la solución usando las sugerencias de nmclean (Muchas gracias) Esta sección establece la agrupación que se usará para distribuir los elementos alrededor de la grilla.
<CollectionViewSource Source="{Binding Source={StaticResource MyDataSource}}" x:Key="cvs">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="ordinal"/>
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
esta sección es el cuadro de lista principal vinculado a los datos en collectionviewsource, The containerstyle contiene los enlaces para poner el elemento de grupo en las celdas correctas en la grilla. La grilla está en 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>
Aquí está la solución total en caso de que la necesite:
<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>
El archivo de código se ve así ahora:
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;
}
}
Estoy vinculando un control de elementos a una fuente de datos y usando una cuadrícula como mis itemshost. Deseo que los elementos se ubiquen en la celda correcta de la cuadrícula (puedo hacerlo), y también se apilan ellos mismos para que no estén uno encima del otro (no puedo imaginar cómo insertar los elementos en una panel de distribución u otro panel en la cuadrícula).
aquí está el archivo .cs para las dos clases:
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;
}
}
}
Aquí está mi 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>
Mi problema es que todos los botones que terminan con ''a'' están debajo de los botones que terminan en b. No veo cómo usar XAML para insertar los elementos en un panel de distribución creado dinámicamente
Traté de crear una clase derivada de Grid, pensando en interceptar la adición de los niños para agregar paneles de distribución yo mismo y luego mover los elementos secundarios de la cuadrícula a los paneles de distribución, pero tratar de manipular los elementos secundarios en un elemento provoca una excepción.
En última instancia, solo quiero que los elementos en mi fuente de datos puedan enlazarse a una ''celda'' en la grilla, y si varios elementos se unen a la misma celda, quiero que se apilen.
Puede hacer esto en el nivel de datos como sugiere HighCore, pero dado que la estructura de datos actual ya contiene la información necesaria, es posible que ItemsControl la maneje. Considere agregar una descripción de grupo a la colección de elementos de ListBox y use un GroupStyle cuyo Panel sea un StackPanel.