web-dev-qa-db-fra.com

WrapPanel comme ItemPanel pour ItemsControl

Je continue à rigoler avec WPF et à apprendre au fur et à mesure. Nous essayons maintenant de construire un groupe dynamique de contrôles (principalement des boutons mais pouvant inclure des CheckBox et d’autres).

Je n'avais aucune idée de la meilleure façon de procéder. J'ai donc essayé de créer un style ItemsControl, puis d'ajouter les éléments dans un ItemsPresenter à l'intérieur d'un WrapPanel. Bientôt, je me suis rendu compte que les articles ne seraient pas emballés car ils ne se trouvaient effectivement pas dans le WrapPanel, à moins que je ne le mette sous le nom de ItemsHost. Comme ça:

<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>

Notez que ceci est un travail en cours et que de nombreux effets de style doivent encore être mis en œuvre. Ici je l'utilise:

<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>

Notez également qu'il s'agit toujours d'un travail en cours, car UniformGrid ne serait pas la solution et que les marges peuvent être pénibles (existe-t-il des marges qui se chevauchent?), Donc les contributions seraient appréciées.

Passons maintenant au vrai problème. Cela ne fonctionne pas je reçois une erreur:

L'objet 'ItemsPresenter' ne peut pas être ajouté à 'WrapPanel'. Impossible de Explicitement de modifier la collection de panneaux de Children utilisée dans ItemsPanel pour ItemsControl. ItemsControl génère des éléments enfants pour Panel. Erreur À l'objet 'System.Windows.Controls.ItemsPresenter'.

Alors, quelle est la meilleure façon de faire quelque chose comme ça (aimerait pouvoir simplement lancer des boutons et d’autres commandes dans le contrôle d’objet et dans la configuration réelle de Nice). Serait-il préférable de mettre les contrôles dans une collection quelconque et de les itérer.

J'adorerais le faire bien mais mes compétences WPF manquent encore. Existe-t-il des livres WPF qui enseignent au-delà des bases et montrent comment les professionnels le feraient réellement?

27
Ingó Vals

Vous voudrez peut-être jeter un coup d'œil à la propriété ItemsPanel :

Obtient ou définit le modèle qui définit le panneau qui contrôle la disposition des éléments. 

Exemple:

<ItemsControl>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

Et vous pouvez le définir dans un style comme suit:

<Style TargetType="ItemsControl">
    <Setter Property="ItemsPanel">
      <Setter.Value>
            <ItemsPanelTemplate>
                <WrapPanel />
            </ItemsPanelTemplate>
        </Setter.Value>
    </Setter>
</Style>
43
Arcturus

N'oubliez pas la définition de la propriété d'indice IsItemsHost = "True". Sinon, ItemsControl ne montrera pas vos éléments.

<ListBox ItemsSource="{Binding MyItemsSource}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate >
                <WrapPanel IsItemsHost="True"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ListBox>
3
Mr.B

Voici une autre alternative simple à la solution lente DataGrid/xceed datagrid et WrapPanel. Cela peut être utile lorsqu'un grand nombre de données ou une table entière est uniquement destinée à l'édition. Utilisation de ItemsControl + Grid.IsSharedSizeScope = "True"

Plus d'informations ici: https://wpf.2000things.com/tag/issharedsizescope/ + À propos de la virutualisation ItemsControl pour la performance: Virtualisation d'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>
0
Evalds Urtans