簡體   English   中英

通過ICommands單擊按鈕刪除ListBoxItem

[英]Remove ListBoxItem on button click through ICommands

我剛開始使用XAML / WPF,腦海中浮現出許多疑問。 其中之一是如何綁定按鈕單擊以通過ICommand接口刪除ListBoxItem 我創建了一個簡單的WPF項目,這是我的XAML:

<ListBox Name="lb" HorizontalAlignment="Left" Height="129" Margin="15,17,0,0" VerticalAlignment="Top" Width="314" Grid.ColumnSpan="2" >
    <ListBox.Resources>
        <Style TargetType="ListBoxItem">
            <Setter Property="Height" Value="30" />
            <Setter Property="OverridesDefaultStyle" Value="true" />
            <Setter Property="SnapsToDevicePixels" Value="true" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ListBoxItem">
                        <StackPanel Orientation="Horizontal">
                            <CheckBox Margin="5,5" Height="18" IsChecked="{TemplateBinding IsSelected}">
                                <ContentPresenter Content="{TemplateBinding Content}"/>
                            </CheckBox>
                            <Button Content="[x]" Height="22" Width="22" HorizontalAlignment="Right" 
                                    Command="{Binding ElementName=lb, Path=DataContext.DeleteItemCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBox}}}" CommandParameter="{Binding }"/>
                        </StackPanel>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ListBox.Resources>
    <ListBoxItem Content="Foo" />
    <ListBoxItem Content="Bar" />
</ListBox>

這是我的窗口:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new Context(); // Also tried before InitializeComponent()
    }

    public class Context
    {
        public ICommand DeleteItemCommand = new DeleteItemCommand();
    }
}

其中DeleteItemCommand為:

public class DeleteItemCommand : ICommand
{
    public event EventHandler CanExecuteChanged;

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public void Execute(object parameter)
    {
        MessageBox.Show("Meep");
    }
}

問題是:

  1. 為什么沒有顯示消息框? 我該如何運作?
  2. 如何檢索哪個索引/ ListBoxItem觸發了按鈕單擊?
  3. 如何將按鈕對准行尾?

非常感謝!

您遇到的一個問題是ICommand只是一個變量。

您需要一個公共屬性才能綁定。

更像

    public ICommand DeleteItemCommand {get;set;} = new DeleteItemCommand();

另一個問題是您的elementname。 這取決於名稱范圍,我想您會發現列表框位於另一個名稱范圍中。

相反,只需將relativesource綁定與ancestortype ListBox一起使用。

大致。

Command="{Binding DataContext.DeleteItemCommand,
RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}

作為旁白。

我建議研究一下一個框架,以簡化命令等操作。

MVVMLight是我的建議。 使用nuget mvvmlightlibs添加到項目。 https://msdn.microsoft.com/en-gb/magazine/dn237302.aspx?f=255&MSPPError=-2147217396

以下內容基於我已經擁有的一些代碼,因此僅是示例性的,而不是您正在執行的操作。

視圖:

<Window.DataContext>
    <local:MainWindowViewModel/>
</Window.DataContext>
<Grid>
    <ListBox ItemsSource="{Binding People}"
             HorizontalContentAlignment="Stretch">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*"/>
                        <ColumnDefinition Width="100"/>
                    </Grid.ColumnDefinitions>
                 <TextBlock Text="{Binding LastName}"/>
                    <Button Content="Delete"
                            Command="{Binding DataContext.DeletePersonCommand, RelativeSource={RelativeSource AncestorType=ListBox}}"
                            CommandParameter="{Binding}"
                            Grid.Column="1"/>
                </Grid>

            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</Grid>

ViewModel使用來自mvvmlight的relaycommand

using GalaSoft.MvvmLight.CommandWpf;
using System.Collections.ObjectModel;
namespace wpf_99
{
public class MainWindowViewModel : BaseViewModel
{
    private RelayCommand<Person> deletePersonCommand;
    public RelayCommand<Person> DeletePersonCommand
    {
        get
        {
            return deletePersonCommand
            ?? (deletePersonCommand = new RelayCommand<Person>(
              (person) =>
              {
                  People.Remove(person);
              }
             ));
        }
    }

    private ObservableCollection<Person> people = new ObservableCollection<Person>();

    public ObservableCollection<Person> People
    {
        get { return people; }
        set { people = value; }
    }

    public MainWindowViewModel()
    {
        People.Add(new Person { FirstName = "Chesney", LastName = "Brown" });
        People.Add(new Person { FirstName = "Gary", LastName = "Windass" });
        People.Add(new Person { FirstName = "Liz", LastName = "McDonald" });
        People.Add(new Person { FirstName = "Carla", LastName = "Connor" });
    }
}
}

BaseViewModel幾乎與inotifypropertychanged上的msdn文章顯示的一樣:

public  class BaseViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void RaisePropertyChanged([CallerMemberName] String propertyName = "")
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Mvvmlight有其自己的基本視圖模型,但是您不能序列化從中繼承的vm。

人員:公共類人員:BaseViewModel {私有字符串firstName;

    public string FirstName
    {
        get { return firstName; }
        set { firstName = value; RaisePropertyChanged(); }
    }
    private string lastName;

    public string LastName
    {
        get { return lastName; }
        set { lastName = value; RaisePropertyChanged(); }
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM