绑定命令从集合中删除self

时间:2016-07-27 15:55:50

标签: c# wpf mvvm

我正在尝试创建一个动态的文本框列表框,通过按下与每个文本框匹配的按钮来添加和删除文本框。我有一切正常工作,但删除,只偶尔适用于最后一项(但并非总是如此)。

我有一个ObservableCollection<ExcludedPath>,其中ExcludedPath类是:

public class ExcludedPath : INotifyPropertyChanged
{
    private Visibility _addButtonVisibility;
    private string _path;

    private ICommand _removeButtonCommand;
    private Visibility _removeButtonVisibility;

    public ICommand RemoveButtonCommand
    {
        get
        {
            return _removeButtonCommand;
        }
        set
        {
            _removeButtonCommand = value;
            NotifyPropertyChanged();
        }
    }

    public Visibility AddButtonVisibility
    {
        get
        {
            return _addButtonVisibility;
        }
        set
        {
            _addButtonVisibility = value;
            NotifyPropertyChanged();
        }
    }

    public string Path
    {
        get
        {
            return _path;
        }
        set
        {
            _path = value;
            NotifyPropertyChanged();
        }
    }

    public ICommand AddButtonCommand { get; set; }

    public Visibility RemoveButtonVisibility
    {
        get
        {
            return _removeButtonVisibility;
        }
        set
        {
            _removeButtonVisibility = value;
            NotifyPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(
        [CallerMemberName] string propertyName = "")
    {
        PropertyChanged?.Invoke(
            this,
            new PropertyChangedEventArgs(propertyName));
    }
}

在我的ViewModel课程中,以下是相关的片段:

internal ViewModel()
{
    SetUpProperties();
}

public ObservableCollection<ExcludedPath> ExcludedPaths { get;
    private set; }

private void AddExcludedPathExecute()
{
    ExcludedPaths.Add(new ExcludedPath());
}

private bool CanAddExcludedPath()
{
    return ExcludedPaths.All(x => !x.Path.IsNullOrWhiteSpace());
}

private bool CanRemoveExcludedPath()
{
    return ExcludedPaths.Count > 1;
}

private void OnExcludedPathsChanged(
    object sender, NotifyCollectionChangedEventArgs e)
{
    var addButtonCommand = new RelayCommand(
        AddExcludedPathExecute, CanAddExcludedPath);

    if (e.Action == NotifyCollectionChangedAction.Add)
    {
        for (var i = 0; i < ExcludedPaths.Count - 1; i++)
        {
            ExcludedPaths[i].AddButtonVisibility = Visibility.Hidden;
        }
        var excludedPath = ExcludedPaths.Last();
        excludedPath.AddButtonCommand = addButtonCommand;
        excludedPath.AddButtonVisibility = Visibility.Visible;
        excludedPath.RemoveButtonCommand = new RelayCommand(
            () => RemoveExcludedPath(excludedPath), 
            CanRemoveExcludedPath);
    }
    else if (e.Action == NotifyCollectionChangedAction.Remove)
    {
        ExcludedPaths.Last().AddButtonVisibility = Visibility.Visible;
    }
}

private void RemoveExcludedPath(ExcludedPath excludedPath)
{
    ExcludedPaths.Remove(excludedPath);
}

private void SetUpProperties()
{
    ExcludedPaths = new ObservableCollection<ExcludedPath>();
    ExcludedPaths.CollectionChanged += OnExcludedPathsChanged;
    ExcludedPaths.Add(new ExcludedPath());
}

我的View

<ListBox ItemsSource="{Binding ExcludedPaths}">
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListBoxItem">
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ListBoxItem">
                        <ContentPresenter/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ListBox.ItemContainerStyle>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <DockPanel LastChildFill="True">
                <Button DockPanel.Dock="Right"
                    Content ="+"
                    Command="{Binding AddButtonCommand}"
                    Visibility="{Binding AddButtonVisibility}"/>
                <Button DockPanel.Dock="Right"
                    Content="-"
                    Command="{Binding RemoveButtonCommand}"
                    Visibility="{Binding RemoveButtonVisibility}"/>
                <TextBox DockPanel.Dock="Left"
                        Text ="{Binding Path, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                        HorizontalAlignment="Stretch"
                        HorizontalContentAlignment="Stretch"/>
            </DockPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

1 个答案:

答案 0 :(得分:3)

处理集合更改事件时,您不应该像过去那样获取最后一项(var excludedPath = ExcludedPaths.Last();),而是迭代e.NewItems

(同样在删除时,您应该遍历e.OldItems。)

我个人处理包含列表的对象中的删除,尽管你的方法应该有效。为了按照我的方式做到这一点,你会像这样绑定它:

<Button Command="{Binding DataContext.RemoveCommand, RelativeSource={RelativeSource AncestorType=ListBox}}"
        CommandParameter="{Binding}"/>

要删除的项目作为命令参数传递。