WrapPanel come ItemPanel per ItemsControl
-
01-10-2019 - |
Domanda
Ancora scherzare con WPF e imparare come vado. Cercando ora di costruire una dinamica di raggruppamento dei comandi (per lo più pulsanti, ma potrebbe includere caselle di controllo e altri).
Non avevo idea di cosa fosse il modo migliore per farlo così ho cercato di creare uno stile ItemsControl e poi aggiungere gli elementi in un ItemsPresenter all'interno di un WrapPanel. Presto realizzato gli elementi non sarebbero avvolgere perché effettivamente non erano all'interno del WrapPanel a meno che non l'ho messo come ItemsHost. In questo modo:
<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>
Si noti che questo è un work in progress e ci sono molti effetti styling ho ancora bisogno di implementare. Qui Io 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>
Si noti inoltre qui che è ancora un work in progress come UniformGrid non sarebbe il modo di andare qui ed anche i margini può essere un dolore (esistono margini che si sovrappongono?) Così ingresso ci sarebbe apprezzato.
Ora per il vero problema. Questo non funziona ottengo un errore:
oggetto 'ItemsPresenter' non può essere aggiunto a 'WrapPanel'. Non può esplicitamente modificare collezione bambini di pannello utilizzato come ItemsPanel per ItemsControl. ItemsControl genera elementi figlio per il pannello. Errore a oggetto 'System.Windows.Controls.ItemsPresenter'.
Allora, qual è il modo migliore per fare qualcosa di simile (mi piacerebbe essere in grado di lanciare solo pulsanti e altri controlli nel ItemControl e la line up davvero bello). Sarebbe meglio mettere i controlli in una collezione di qualche tipo e iterare.
piacerebbe farlo ben fatto ma le mie capacità WPF sono ancora carente. Ci sono dei libri WPF che insegnano al di là delle nozioni di base e mostrare come Pro sarebbe davvero farlo?
Soluzione
Si potrebbe desiderare di dare un'occhiata al ItemsPanel proprietà:
Ottiene o imposta il modello che definisce il pannello che controlla il layout di elementi.
Esempio:
<ItemsControl>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
Ed è possibile impostare in uno stile come segue:
<Style TargetType="ItemsControl">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
</Style>
Altri suggerimenti
Non dimenticate definizione di proprietà indizio IsItemsHost = "True". In caso contrario, il vostro ItemsControl non mostrerà i tuoi articoli.
<ListBox ItemsSource="{Binding MyItemsSource}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate >
<WrapPanel IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ListBox>
Ecco un altro semplice alternativa a rallentare / Xceed DataGrid e DataGrid soluzione WrapPanel. Potrebbe essere utile quando un sacco di dati o tavolo insieme è solo per la modifica. Utilizzando ItemsControl + Grid.IsSharedSizeScope = "True"
Più informazioni su: https://wpf.2000things.com/tag/issharedsizescope/ + Su ItemsControl virutualization per le prestazioni:? Virtualizzazione di 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>