Search code examples
.netwpfstackpanelwrappanel

Dynamically Add and Remove stack panel


enter image description here

I have one WrapPanel (with green background) inside of a ListBox(with gray background).

I am trying to dynamically add a StackPanel multiple times (by clicking on the button below given image) in the WrapPanel.

The StackPanel contains a Button which has Content “X”. I want to remove individual StackPanel objects (with orange background) when this button is clicked.

How can it be worked out?


Solution

  • Data Binding & Data Templating + Commanding

    Your question is kind of extensive. The basic outline is to create bindable collections, data template them, and remove the clicked item from it using a command or event.

    Example of DataTemplating using an ItemsControl that internally uses a WrapPanel for the layout:

    <ItemsControl ItemsSource="{Binding DpData}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <WrapPanel />
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <!-- The content goes here, X-Button will be overlayed -->
                    <Button HorizontalAlignment="Right"
                            VerticalAlignment="Top"
                            Content="X" Click="RemoveItem_Click"/>
                </Grid>
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
    
    // Does not need to be a dependency property.
    public static readonly DependencyProperty DpDataProperty =
        DependencyProperty.Register("DpData", typeof(ObservableCollection<Employee>), typeof(MainWindow), new UIPropertyMetadata(new ObservableCollection<Employee>()));
    public ObservableCollection<Employee> DpData
    {
        get { return (ObservableCollection<Employee>)GetValue(DpDataProperty); }
        set { SetValue(DpDataProperty, value); }
    }
    
    // For simplicity i use an event instead of a command.
    private void RemoveItem_Click(object sender, RoutedEventArgs e)
    {
        var button = (FrameworkElement)sender;
        var emp = (Employee)button.DataContext;
        DpData.Remove(emp);
    }
    

    If you do it like this you should of course not add a panel upon add-button click but a data item to the collection. The panel will be generated automatically.