wpf - WrapPanel como ItemPanel para ItemsControl
listboxitem wpf (3)
Sigo jugando con WPF y aprendiendo sobre la marcha. Intentando ahora construir una agrupación dinámica de controles (en su mayoría, botones, pero puede incluir CheckBoxes y otros).
No tenía idea de cuál era la mejor manera de hacer esto, así que intenté crear un estilo de ItemsControl y luego agregar los artículos a un ItemsPresenter dentro de un WrapPanel. Pronto se dio cuenta de que los elementos no se envolverían porque efectivamente no estaban dentro del WrapPanel a menos que los pusiera como ItemsHost. Me gusta esto:
<Style x:Key="ButtonPanelGroup" TargetType="{x:Type ItemsControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ItemsControl}">
<Border CornerRadius="5"
BorderBrush="{StaticResource DarkColorBrush}"
BorderThickness="1"
Margin="5">
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<WrapPanel IsItemsHost="True" FlowDirection="LeftToRight">
<ItemsPresenter />
</WrapPanel>
<ContentPresenter ContentSource="Name" Grid.Row="1" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Tenga en cuenta que este es un trabajo en progreso y hay muchos efectos de estilo que aún debo implementar. Aquí lo uso:
<UniformGrid Rows="1">
<ItemsControl Name="Group1" Style="{StaticResource ButtonPanelGroup}">
<Button>Button1</Button>
<Button>Button2</Button>
<CheckBox>TickBox</CheckBox>
</ItemsControl>
<ItemsControl Name="Group2" Style="{StaticResource ButtonPanelGroup}">
<Button>Button3</Button>
<Button>Button4</Button>
<Button>Button5</Button>
</ItemsControl>
<ItemsControl Name="Group3" Style="{StaticResource ButtonPanelGroup}">
<Button>Button6</Button>
<Button>Button7</Button>
<Button>Button8</Button>
</ItemsControl>
</UniformGrid>
También tenga en cuenta que aún se trata de un trabajo en progreso, ya que UniformGrid no sería el camino a seguir y que los márgenes pueden ser una molestia (¿hay márgenes que se superpongan?), Por lo que se agradecería la entrada.
Ahora al problema real. Esto no funciona me sale un error:
El objeto ''ItemsPresenter'' no se puede agregar a ''WrapPanel''. No se puede modificar explícitamente la colección Children del Panel utilizado como ItemsPanel para ItemsControl. ItemsControl genera elementos secundarios para el Panel. Error en el objeto ''System.Windows.Controls.ItemsPresenter''.
Entonces, ¿cuál es la mejor manera de hacer algo como esto (me encantaría poder simplemente lanzar botones y otros controles en el Control de Artículos y la alineación realmente agradable). ¿Sería mejor poner los controles en una colección de algún tipo y iterar?
Me encantaría hacerlo bien, pero todavía faltan mis habilidades de WPF. ¿Hay libros de WPF que enseñen más allá de lo básico y muestren cómo los profesionales realmente lo harían?
Aquí hay otra alternativa simple para reducir la velocidad de DataGrid / xceed datagrid y WrapPanel. Podría ser útil cuando una gran cantidad de datos o toda la tabla es solo para editar. Utilizando ItemsControl + Grid.IsSharedSizeScope = "True"
Más información aquí: https://wpf.2000things.com/tag/issharedsizescope/ + En la virtualización de ItemsControl para el rendimiento: ¿ Virtualizar un ItemsControl?
<Grid Grid.IsSharedSizeScope="True" Margin="0,30,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="50" Width="Auto" SharedSizeGroup="Id" />
<ColumnDefinition MinWidth="50" Width="Auto" SharedSizeGroup="Time" />
</Grid.ColumnDefinitions>
<Border Grid.Column="0" >
<TextBlock VerticalAlignment="Center" TextWrapping="NoWrap" Text="Header1" />
</Border>
<Border Grid.Column="1" >
<TextBlock VerticalAlignment="Center" TextWrapping="NoWrap" Text="Header2" />
</Border>
</Grid>
<ItemsControl Grid.Row="1" ItemsSource="{Binding RunInstance.ConcentrationGradient.Steps}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition MinWidth="50" Width="Auto" SharedSizeGroup="Id" />
<ColumnDefinition MinWidth="50" Width="Auto" SharedSizeGroup="Time" />
</Grid.ColumnDefinitions>
<Border Grid.Column="0">
<TextBlock VerticalAlignment="Center" TextWrapping="NoWrap" Text="{Binding Index, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" />
</Border>
<Border Grid.Column="1">
<TextBlock VerticalAlignment="Center" TextWrapping="NoWrap" Text="{Binding Time, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" />
</Border>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
Es posible que desee echar un vistazo a la propiedad ItemsPanel :
Obtiene o establece la plantilla que define el panel que controla el diseño de los elementos.
Ejemplo:
<ItemsControl>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
Y puedes configurarlo en un estilo de la siguiente manera:
<Style TargetType="ItemsControl">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
No olvide la definición de la propiedad de pista IsItemsHost = "True". De lo contrario, su ItemsControl no mostrará sus artículos.
<ListBox ItemsSource="{Binding MyItemsSource}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate >
<WrapPanel IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ListBox>