我看到您正在处理按钮单击事件,大概是在窗口/控件后面的代码中。这会在 UI 元素和背后的逻辑之间产生强烈的耦合,从而使测试变得更加困难。
我会考虑使用MVVM pattern 并在视图模型中执行此类操作。使用这种方法可以减少 UI(视图)和逻辑(视图模型)之间的耦合。
我已经组装了一个非常简单的应用程序(针对 .Net 4.5)来演示将集合绑定到数据网格以及如何删除选定的行。
MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow"
Width="525"
Height="350">
<Grid>
<StackPanel>
<DataGrid ItemsSource="{Binding People}" SelectedItem="{Binding SelectedItem}" />
<Button Command="{Binding DeleteCommand}">Delete Selected Row</Button>
</StackPanel>
</Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Windows;
using System.Windows.Input;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainViewModel();
}
}
Person.cs
using System;
namespace WpfApplication1
{
public class Person
{
public string Forename { get; set; }
public string Surname { get; set; }
}
}
DelegateCommand.cs
using System;
using System.Windows;
using System.Windows.Input;
namespace WpfApplication1
{
public class DelegateCommand : ICommand
{
private readonly Predicate<object> _canExecute;
private readonly Action<object> _execute;
public event EventHandler CanExecuteChanged;
public DelegateCommand(Action<object> execute)
: this(execute, null)
{
}
public DelegateCommand(Action<object> execute,
Predicate<object> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
if (_canExecute == null)
{
return true;
}
return _canExecute(parameter);
}
public void Execute(object parameter)
{
_execute(parameter);
}
public void RaiseCanExecuteChanged()
{
if (CanExecuteChanged != null)
{
CanExecuteChanged(this, EventArgs.Empty);
}
}
}
}
MainViewModel.cs
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows.Input;
namespace WpfApplication1
{
internal class MainViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public MainViewModel()
{
People = new ObservableCollection<Person>();
DeleteCommand = new DelegateCommand(x => DeleteSelectedItem(null));
People.Add(new Person { Forename = "Bob", Surname = "Smith" });
People.Add(new Person { Forename = "Alice", Surname = "Jones" });
}
private void DeleteSelectedItem(object obj)
{
People.Remove(SelectedItem);
SelectedItem = null;
}
public ICommand DeleteCommand { get; set; }
public ObservableCollection<Person> People { get; set; }
private Person selectedItem;
public Person SelectedItem
{
get { return selectedItem; }
set
{
if (selectedItem == value)
return;
selectedItem = value;
OnPropertyChanged();
}
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
背后的代码
MainWindow.xaml.cs
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
DeleteCommand = new DelegateCommand(x => DeleteSelectedItem(null));
People = new ObservableCollection<Person>();
DataContext = this;
Loaded += (sender, args) => PopulateCollection();
}
public event PropertyChangedEventHandler PropertyChanged;
private void PopulateCollection()
{
People.Add(new Person { Forename = "Bob", Surname = "Smith" });
People.Add(new Person { Forename = "Alice", Surname = "Jones" });
}
private void DeleteSelectedItem(object obj)
{
People.Remove(SelectedItem);
SelectedItem = null;
}
public ICommand DeleteCommand { get; set; }
public ObservableCollection<Person> People { get; set; }
private Person selectedItem;
public Person SelectedItem
{
get { return selectedItem; }
set
{
if (selectedItem == value)
return;
selectedItem = value;
OnPropertyChanged();
}
}
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}