我正在尝试在DataGrid中显示记录,并且对于网格上的每一行,我想显示一个删除该记录的按钮。
我已成功将按钮添加到dataGrid。但是,当加载视图时,"删除"为每条记录调用命令。换句话说,我确认对话框出现10次,因为我有10条记录要显示。
问题 如何阻止命令每次执行,只允许它在按钮点击时运行? 另外,如何将最后2列一直移动到最右边,使它们垂直对齐?
在我的ViewModel中,我添加了以下命令
public ICommand DeleteVendor
{
get
{
MessageBoxResult confirmation = MessageBox.Show("Are you sure?", "Delete Confirmation", MessageBoxButton.YesNo);
bool processDelete = (confirmation == MessageBoxResult.Yes);
return new ActionCommand(p => HandleDeleteVendor(), p => processDelete);
}
}
private void HandleDeleteVendor()
{
if (SelectedVendor == null)
{
throw new Exception("No vendor was selected");
}
UnitOfWork.Vendors.Remove(SelectedVendor);
UnitOfWork.Save();
}
然后在我看来,我添加了以下XAML
代码
<DataGrid ItemsSource="{Binding Vendors}"
SelectedItem="{Binding SelectedVendor}"
AutoGenerateColumns="False"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
CanUserAddRows="False">
<DataGrid.Columns>
<DataGridTextColumn Header="Name"
Binding="{Binding Name}" />
<DataGridTextColumn Header="Account Number"
Binding="{Binding AccountCode}" />
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button VerticalAlignment="Center"
Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}},
Path=DataContext.ShowVendor}">
<StackPanel Orientation="Horizontal">
<fa:FontAwesome Icon="Eye"
FontSize="18" />
<Label Content="Details"
Padding="7 0 0 0" />
</StackPanel>
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<Button VerticalAlignment="Center"
Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}},
Path=DataContext.DeleteVendor}">
<StackPanel Orientation="Horizontal">
<fa:FontAwesome Icon="Trash"
FontSize="18" />
<Label Content="Delete"
Padding="7 0 0 0" />
</StackPanel>
</Button>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
如果需要,我的ICommand
实施
public sealed class ActionCommand : ICommand
{
private readonly Action<Object> Action;
private readonly Predicate<Object> Allowed;
/// <summary>
/// Initializes a new instance of the <see cref="ActionCommand"/> class.
/// </summary>
/// <param name="action">The <see cref="Action"/> delegate to wrap.</param>
public ActionCommand(Action<Object> action)
: this(action, null)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ActionCommand"/> class.
/// </summary>
/// <param name="action">The <see cref="Action"/> delegate to wrap.</param>
/// <param name="predicate">The <see cref="Predicate{Object}"/> that determines whether the action delegate may be invoked.</param>
public ActionCommand(Action<Object> action, Predicate<Object> allowed)
{
if (action == null)
{
throw new ArgumentNullException("action", "You must specify an Action<T>.");
}
Action = action;
Allowed = allowed;
}
/// <summary>
/// Defines the method that determines whether the command can execute in its current state.
/// </summary>
/// <returns>
/// true if this command can be executed; otherwise, false.
/// </returns>
/// <param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to null.</param>
public bool CanExecute(object parameter)
{
if (Allowed == null)
{
return true;
}
return Allowed(parameter);
}
/// <summary>
/// Defines the method to be called when the command is invoked.
/// </summary>
/// <param name="parameter">Data used by the command. If the command does not require data to be passed, this object can be set to null.</param>
public void Execute(object parameter)
{
Action(parameter);
}
/// <summary>
/// Executes the action delegate without any parameters.
/// </summary>
public void Execute()
{
Execute(null);
}
/// <summary>
/// Occurs when changes occur that affect whether the command should execute.
/// </summary>
public event EventHandler CanExecuteChanged
{
add
{
if (Allowed != null)
{
CommandManager.RequerySuggested += value;
}
}
remove
{
if (Allowed != null)
{
CommandManager.RequerySuggested -= value;
}
}
}
/// <summary>
/// Raises the <see cref="CanExecuteChanged" /> event.
/// </summary>
public void RaiseCanExecuteChanged()
{
CommandManager.InvalidateRequerySuggested();
}
}
答案 0 :(得分:1)
确认应该是delete方法的一部分,而不是命令定义的一部分:
public ICommand DeleteVendor
{
get
{
return new ActionCommand(p => HandleDeleteVendor(), p => SelectedVendor != null);
}
}
private void HandleDeleteVendor()
{
MessageBoxResult confirmation = MessageBox.Show("Are you sure?", "Delete Confirmation", MessageBoxButton.YesNo);
if (confirmation != MessageBoxResult.Yes);
return;
if (SelectedVendor == null)
{
// IMO, it is better to handle this situation gracefully and show messageBox with a warning
throw new Exception("No vendor was selected");
}
UnitOfWork.Vendors.Remove(SelectedVendor);
UnitOfWork.Save();
}