我正在尝试创建一个动态的文本框列表框,通过按下与每个文本框匹配的按钮来添加和删除文本框。我有一切正常工作,但删除,只偶尔适用于最后一项(但并非总是如此)。
我有一个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>
答案 0 :(得分:3)
处理集合更改事件时,您不应该像过去那样获取最后一项(var excludedPath = ExcludedPaths.Last();
),而是迭代e.NewItems
。
(同样在删除时,您应该遍历e.OldItems
。)
我个人处理包含列表的对象中的删除,尽管你的方法应该有效。为了按照我的方式做到这一点,你会像这样绑定它:
<Button Command="{Binding DataContext.RemoveCommand, RelativeSource={RelativeSource AncestorType=ListBox}}"
CommandParameter="{Binding}"/>
要删除的项目作为命令参数传递。