简体   繁体   中英

How to add a “Remove” button to each item of a ListBox and implement its functionality?

I need a "Remove" button for each item in the listbox of a UserControl. I am trying to use a ListBox Template.

<UserControl.Resources>
    <DataTemplate x:Key="ListBoxItemTemplate">
        <Grid>
            <TextBlock x:Name="TB" Height="23" Text="" VerticalAlignment="Top" />
            <Button Margin="500,0,0,0" Width="80" Click="Button_Click">remove</Button>
        </Grid>
    </DataTemplate>
</UserControl.Resources>

<ListBox x:Name="listbox" ItemTemplate="{StaticResource ListBoxItemTemplate}" SelectionChanged="ListBox_SelectionChanged"/>

How to make the text content of each item specified by the back-end code as shown below and how does the "remove" button remove its corresponding item? Thanks.

listbox.Items.Add("111");
listbox.Items.Add("222");

Simpliest solution would be to use the ICommand system of WPF. Using this, you can bind your current item to the commands parameter, and use that in code beind.

(I am using window, not user control, but you can just change that..

This is the WPF :

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        mc:Ignorable="d"
        Title="MainWindow" x:Name="Window" Height="350" Width="525">
    <Window.Resources>
        <DataTemplate x:Key="ListBoxItemTemplate">
            <Grid>
                <TextBlock Height="23" Text="{Binding}" VerticalAlignment="Top" />
                <Button Margin="500,0,0,0" Width="80" CommandParameter="{Binding}" Command="{Binding ElementName=Window, Path=OnClickCommand}">remove</Button>
            </Grid>
        </DataTemplate>
    </Window.Resources>

    <ListBox x:Name="listbox" ItemTemplate="{StaticResource ListBoxItemTemplate}" />

</Window>

{Binding} means to bind the current object the template is used on (in this instance, the string in my implementation.

The OnClickCommand is what does the magic.

C#:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        listbox.Items.Add("asdf");
        listbox.Items.Add("fdsfsadf");
        listbox.Items.Add("dfsd");
        listbox.Items.Add("a sdfas");
        listbox.Items.Add("asdgas g");

        //This is the command that gets executed.
        OnClickCommand = new ActionCommand(x => listbox.Items.Remove(x));
    }

    public ICommand OnClickCommand { get; set; }
}

//This implementation of ICommand executes an action.
public class ActionCommand : ICommand
{
    private readonly Action<object> Action;
    private readonly Predicate<object> Predicate;

    public ActionCommand(Action<object> action) : this(action, x => true)
    {

    }
    public ActionCommand(Action<object> action, Predicate<object> predicate)
    {
        Action = action;
        Predicate = predicate;
    }

    public bool CanExecute(object parameter)
    {
        return Predicate(parameter);
    }
    public void Execute(object parameter)
    {
        Action(parameter);
    }

    //These lines are here to tie into WPF-s Can execute changed pipeline. Don't worry about it.
    public event EventHandler CanExecuteChanged
    {
        add
        {
            CommandManager.RequerySuggested += value;
        }
        remove
        {
            CommandManager.RequerySuggested -= value;
        }
    }
}

Note that it doesn't matter whether you use string or any other type of object, because {Binding} gets the current object that is in the ListBox.Items list

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM