C# 删除按钮上的ListBoxItem单击图标命令
我刚开始学习XAML/WPF,脑子里有很多问题。其中之一是如何通过ICommand界面绑定按钮单击以删除C# 删除按钮上的ListBoxItem单击图标命令,c#,wpf,xaml,listbox,C#,Wpf,Xaml,Listbox,我刚开始学习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.Re
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>
其中DeleteItemCommand
为:
public class DeleteItemCommand : ICommand
{
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
MessageBox.Show("Meep");
}
}
问题是:
ListBoxItem
点击非常感谢 这里的一个问题是您的ICommand只是一个变量 您需要一个公共属性才能绑定 更像
public ICommand DeleteItemCommand {get;set;} = new DeleteItemCommand();
另一个问题是你的元素名。这取决于名称范围,我想你会发现列表框在另一个名称范围中
相反,只需将relativesource绑定与ancestortype ListBox一起使用即可
大概吧
Command="{Binding DataContext.DeleteItemCommand,
RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}
作为旁白
我建议研究一个框架,使命令等更容易
MVVMLight将是我的建议。使用nuget mvvmlightlibs添加到项目
下面是基于我已经拥有的一些代码,因此它是说明性的,而不是您正在做的事情
视图:
Mvvmlight有自己的基本viewmodel,但不能序列化从该模型继承的vm
人:
公共类人员:BaseViewModel
{
私有字符串名
public string FirstName
{
get { return firstName; }
set { firstName = value; RaisePropertyChanged(); }
}
private string lastName;
public string LastName
{
get { return lastName; }
set { lastName = value; RaisePropertyChanged(); }
}
您好@Andy!谢谢您的回复。为该命令提供访问器使其正常工作。对于这个丑陋的
相对资源问题,有什么解决方法吗?!还有,我如何将按钮对齐到绝对右侧?以及……我如何检索按钮的ListBoxItem索引?您意识到每个线程应该只有一个问题吗?相对资源-您可以您可能会将datacontext作为一种资源,但我建议您不要认为它看起来很难看。至少现在是这样。如果您想要右上角和左上角的内容,请使用带列的网格而不是stackpanel。不要使用索引,请将行viewmodel传递给命令CommandParameter=“{Binding}”我对WPF比较陌生,最好是一个完整的示例。在这种情况下,在同一上下文中创建多个线程没有任何意义。此外,我不知道如何“将行视图模型传递给命令”。
<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>
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" });
}
}
}
public class BaseViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged([CallerMemberName] String propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public string FirstName
{
get { return firstName; }
set { firstName = value; RaisePropertyChanged(); }
}
private string lastName;
public string LastName
{
get { return lastName; }
set { lastName = value; RaisePropertyChanged(); }
}