问题
Is there any way to stop the Button command execution based on some condition on its click event?
Actually I want to have confirmation popup on some of the button click in our application. To make it a general solution, I have done the following:
- I have extension of WPF button class call
AppBarButton
which already contains some dependency properties. - I have 2 more properties for this as below:
IsActionConfirmationRequired
andConfirmationActionCommand
.
If IsActionConfirmationRequired
then on left button cick event I am opening the confirmation popup.
Is there any way to avoid creating new ConfirmationActionCommand
, and use the same Command
property of the Button
? The problem I am getting if I set Command
, then on Button
click even if user not confirmed the action still button command execute.
C#:
public class AppBarButton : Button
{
public AppBarButton()
{
this.Click += AppBarButton_Click;
}
private void AppBarButton_Click(object sender, RoutedEventArgs e)
{
Button button = sender as Button;
if (button == null || IsActionConfirmationRequired == false || ConfirmationActionCommand == null)
return;
const string defaultMessage = "Do you really want to {0}";
string confirmationPopUpMessage = string.IsNullOrEmpty(ActionConfirmationMessage)
? DebugFormat.Format(defaultMessage, button.Content)
: ActionConfirmationMessage;
ConfirmationDailogDetails confirmationDailogDetails = new ConfirmationDailogDetails
{
Message = confirmationPopUpMessage,
ActionName = button.Content.ToString(),
Template = button.Template,
ActionCommand = ConfirmationActionCommand
};
//instead of ConfirmationActionCommand want to use base.Command
ConfirmationDailog dialog = new ConfirmationDailog(confirmationDailogDetails)
{
PlacementTarget = button,
IsOpen = true
};
}
public static readonly DependencyProperty IsActionConfirmationRequiredProperty =
DependencyProperty.Register("IsActionConfirmationRequired", typeof(bool), typeof(AppBarButton));
public static readonly DependencyProperty ActionConfirmationMessageProperty =
DependencyProperty.Register("ActionConfirmationMessage", typeof(string), typeof(AppBarButton));
public static readonly DependencyProperty ConfirmationActionCommandProperty =
DependencyProperty.Register("ConfirmationActionCommand", typeof(ICommand), typeof(AppBarButton));
/// <summary>
/// Gets or sets the flag to show the confirmation popup on before taking any action on App Bar button click.
/// Also its required to set the command in Tag Property of the App Bar button not in the Command Property, then only required command will fire only when user
/// confirms and click on the action button on confirmation popup.
/// </summary>
public bool IsActionConfirmationRequired
{
get { return (bool)GetValue(IsActionConfirmationRequiredProperty); }
set { SetValue(IsActionConfirmationRequiredProperty, value); }
}
/// <summary>
/// Gets or sets the confirmation message in confirmation popup before taking any action on App Bar button click.
/// </summary>
public ICommand ConfirmationActionCommand
{
get { return (ICommand)GetValue(ConfirmationActionCommandProperty); }
set { SetValue(ConfirmationActionCommandProperty, value); }
}
}
XAML:
<controls:AppBarButton x:Key="WithdrawAll"
AppBarOrder="1"
PageIndex="1"
AppBarOrientation="Left"
Content="Withdraw" IsActionConfirmationRequired="True"
ConfirmationActionCommand="{Binding WithdrawAllCommand}"
Template="{StaticResource DeleteCircleIcon}" />
Please suggest something. I am not able to find anything. Already tried CanExecute
to false, but its make button disable so no use. I just simple dont want make another command, and developer who will use this AppBarButton
need to set ConfirmationActionCommand
not normal Command
.
回答1:
If I correctly understand, you want to confirm user's action and execute a command which is stored in the ButtonBase.Command
property.
To achieve that remove the ConfirmationActionCommand
property and use the OnClick
method instead of the Click
event. In the overriden OnClick
method call the base method which will execute a command from the Command
property if an user confirmed an action or there is no confirmation required.
public class AppBarButton : Button
{
public static readonly DependencyProperty IsActionConfirmationRequiredProperty =
DependencyProperty.Register("IsActionConfirmationRequired", typeof(bool), typeof(AppBarButton));
public static readonly DependencyProperty ActionConfirmationMessageProperty =
DependencyProperty.Register("ActionConfirmationMessage", typeof(string), typeof(AppBarButton));
public bool IsActionConfirmationRequired
{
get { return (bool)GetValue(IsActionConfirmationRequiredProperty); }
set { SetValue(IsActionConfirmationRequiredProperty, value); }
}
public string ActionConfirmationMessage
{
get { return (string)GetValue(ActionConfirmationMessageProperty ); }
set { SetValue(ActionConfirmationMessageProperty , value); }
}
protected override void OnClick()
{
bool confirmed = true;
if (IsActionConfirmationRequired)
{
ConfirmationDailogDetails confirmationDailogDetails = new ConfirmationDailogDetails
{
Message = confirmationPopUpMessage,
ActionName = button.Content.ToString(),
Template = button.Template,
ActionCommand = ConfirmationActionCommand
};
ConfirmationDailog dialog = new ConfirmationDailog(confirmationDailogDetails)
{
PlacementTarget = button,
IsOpen = true
};
// Set confirmed here
// If you set the DialogResult property in the ConfirmationDailog class then
// confirmed = dialog.ShowDialog().Value;
}
// If there is no confirmation requred or if an user have confirmed an action
// then call base method which will execute a command if it exists.
if (confirmed)
{
base.OnClick();
}
}
}
回答2:
Instead of the click event, handle the PreviewMouseLeftButtonDown
event. This occurs before the command executes. In the handler ask for confirmation and set the Handled
property of the event
to true or false.
If you set it to true, the command will not be executed.
private void btn_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
var confirmed = true; //use your confirmation instead
e.Handled = confirmed;
}
Here is how your code could look like (I dont know exactly because I dont have the code for ConfirmationDailog
:
public class AppBarButton : Button
{
public AppBarButton()
{
this.PreviewMouseLeftButtonDown += AppBarButton_PreviewMouseLeftButtonDown; ;
}
private void AppBarButton_PreviewMouseLeftButtonDown(object sender, RoutedEventArgs e)
{
Button button = sender as Button;
if (button == null || IsActionConfirmationRequired == false || ConfirmationActionCommand == null)
return;
const string defaultMessage = "Do you really want to {0}";
string confirmationPopUpMessage = string.IsNullOrEmpty(ActionConfirmationMessage)
? DebugFormat.Format(defaultMessage, button.Content)
: ActionConfirmationMessage;
ConfirmationDailogDetails confirmationDailogDetails = new ConfirmationDailogDetails
{
Message = confirmationPopUpMessage,
ActionName = button.Content.ToString(),
Template = button.Template,
ActionCommand = ConfirmationActionCommand
};
**//instead of ConfirmationActionCommand want to use base.Command**
ConfirmationDailog dialog = new ConfirmationDailog(confirmationDailogDetails)
{
PlacementTarget = button,
IsOpen = true
};
//validation here
dialog.ShowDialog();
var confirmed = dialog.IsConfirmed;
e.Handled = confirmed;
}
...
来源:https://stackoverflow.com/questions/33283210/how-to-stop-the-button-command-execution-from-its-click-event-wpf