2016-07-27 2 views
0

Я пытаюсь создать динамический список текстовых полей, где текстовые поля добавляются и удаляются, нажимая кнопки, соответствующие каждому текстовому полю. У меня все работает, но удаление, которое только изредка работает на последнем пункте (но не всегда).Привязать команду, чтобы удалить себя из коллекции

У меня есть 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> 

ответ

3

При обработке коллекции ch вы должны не просто получить последний элемент, как вы делали (var excludedPath = ExcludedPaths.Last();), но итерации свыше e.NewItems.

(Точно так же при удалении вы должны перебрать e.OldItems.)


Лично я обрабатывать удаление в объект, содержащий список, хотя ваш подход должен работать. Для этого нужно связать это следующим образом:

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

Элемент для удаления передается как параметр команды.

+0

Не исправляет проблему. Я все еще могу удалить только последний объект, и это не работает последовательно. –

+0

Я думал, что это может быть связано с неправильным захватом переменных, но код действительно не выглядит так. Вы всегда можете попробовать сделать это по-другому (см. Править). –

+0

@MichaelBrandonMorris: Кроме того, что вы подразумеваете под непоследовательно? Ничего не происходит при нажатии? –

Смежные вопросы