简体   繁体   中英

MVVM, Button in a ItemsControl, ICommand

Having trouble trying to implement a Command on a button using ICommand/RelayCommand where when you press a button in a list, it removes the item.

I have looked up ICommand/Relay Command, have had numerous attempts at implementing it, but with no success. I think I would also need to pass a parameter (Of type BaseItem) to remove from BaseList.

Im also not sure if the method for removing the Item from the List should go in the Model or the ViewModel. If it was in the Model, I would need to somehow get a reference to BaseList to call BaseList.Remove()?

Code I have so Far,

View

<Window x:Class="WpfApp3.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:WpfApp3"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:TillViewModel/>
    </Window.DataContext>
    <Grid>
        <StackPanel>
            <ItemsControl ItemsSource="{Binding BaseList}">
                <ItemsControl.ItemsPanel>
                    <ItemsPanelTemplate>
                        <VirtualizingStackPanel/>
                    </ItemsPanelTemplate>
                </ItemsControl.ItemsPanel>
                <ItemsControl.Resources>
                    <DataTemplate DataType="{x:Type local:FirstType}">
                        <StackPanel Background="Black"  Orientation="Horizontal">
                            <TextBlock Foreground="White" Text="{Binding Name}"/>
                            <TextBlock Foreground="White" Text=" - "/>
                            <TextBlock Foreground="White" Text="{Binding ProductType}"/>
                            <Button CommandParameter="{Binding MyList}" Content="X" />
                        </StackPanel>
                    </DataTemplate>
                    <DataTemplate DataType="{x:Type local:SecondType}">
                        <StackPanel Background="BurlyWood" Orientation="Horizontal">
                            <TextBlock Text="{Binding Name}"/>
                            <TextBlock Text=" - "/>
                            <TextBlock Text="{Binding ModelType}"/>
                            <Button Content="X"/>
                        </StackPanel>
                    </DataTemplate>
                </ItemsControl.Resources>
            </ItemsControl>
        </StackPanel>
    </Grid>
</Window>

ViewModel (F1, F2, S1 entered in the constructor for time being, just to see it in action so to speak)

public class TillViewModel
{
    private ObservableCollection<BaseItem> _BaseList = new ObservableCollection<BaseItem>();
    public ObservableCollection<BaseItem> BaseList
    {
        get
        {
            return _BaseList;
        }
        set
        {
            _BaseList = value;
        }
    }

    public TillViewModel()
    {
        FirstType F1 = new FirstType() { Name = "Colgate", ProductType = "ToothPaste" };
        FirstType F2 = new FirstType() { Name = "Walkers", ProductType = "Crisps" };
        SecondType S1 = new SecondType() { Name = "Ford", ModelType = "Focus" };

        BaseList.Add(F1);
        BaseList.Add(F2);
        BaseList.Add(S1);
    }
}

Model(s)

public class BaseItem : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
    }
    protected bool SetField<T>(ref T field, T value, string propertyName)
    {
        if (EqualityComparer<T>.Default.Equals(field, value)) return false;
        field = value;
        OnPropertyChanged(propertyName);
        return true;
    }

    private string _Name;
    public string Name
    {
        get => _Name;
        set { SetField(ref _Name, value, nameof(Name)); }
    }

    public BaseItem()
    {

    }
}


public class FirstType : BaseItem
{
    private string _ProductType;
    public string ProductType
    {
        get => _ProductType;
        set { SetField(ref _ProductType, value, nameof(ProductType)); }
    }

    public FirstType()
    {

    }

}

public class SecondType : BaseItem
{
    private string _ModelType;
    public string ModelType
    {
        get => _ModelType;
        set { SetField(ref _ModelType, value, nameof(ModelType)); }
    }

    public SecondType()
    {

    }
}

First, pass the BaseList object to all the BaseItem objects (inject it using the BaseItem constructor, for example). Then, in the button command handler, you can use BaseList.Remove(this); to remove the BaseItem object from the collection.

As for the command, you have to bind the Button Command property to the RelayCommand / ICommand object.

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