我试图建立一种行为,禁用该按钮并更改文本以遵循常见模式禁用按钮来停止用户双击。我需要行为更改在命令前生效。我能以这种方式使用行为吗?如何在Silverlight中的命令之前触发行为 - 禁用双击?
视图:(设置在DataContext在后面的代码的加载事件)
<Grid x:Name="LayoutRoot" Background="White">
<Button Height="50" Width="150" Content="Save" Command="{Binding ButtonClickedCommand}" IsEnabled="{Binding IsNextButtonEnabled}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<behaviors:SubmitButtonBehavior LoadingButtonText="WAIT!!!..." IsEnabled="True" IsFinished="{Binding IsFinishedSubmitButtonBehavior}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</Grid>
视图模型
使用System.Windows; 使用GalaSoft.MvvmLight;使用GalaSoft.MvvmLight.Command的 ; 命名空间SubmitButtonBehaviorTest { 公共类MainPageViewModel:ViewModelBase {/// /// 私人isFinishedSubmitButtonBehavior财产。 ///
private bool isFinishedSubmitButtonBehavior;
public bool IsFinishedSubmitButtonBehavior
{
get
{
return this.isFinishedSubmitButtonBehavior;
}
set
{
this.isFinishedSubmitButtonBehavior = value;
this.RaisePropertyChanged("IsFinishedSubmitButtonBehavior");
}
}
/// <summary>
/// Private ButtonClickedCommand property.
/// </summary>
private RelayCommand buttonClickedCommand;
public RelayCommand ButtonClickedCommand
{
get
{
return this.buttonClickedCommand;
}
private set
{
this.buttonClickedCommand = value;
}
}
public MainPageViewModel()
{
this.ButtonClickedCommand = new RelayCommand(
() =>
{
MessageBox.Show("Clicked");
this.IsFinishedSubmitButtonBehavior = true;
});
}
}
}
行为:使用System.Windows
namespace SubmitButtonBehaviorTest.Behaviors
{ ; using System.Windows.Controls; using System.Windows.Interactivity;
/// <summary>
/// Attach this behavior to disable the button on click and change the text
/// </summary>
public class SubmitButtonBehavior : TriggerAction<UIElement>
{
/// <summary>
/// The original button text, reset when the IsEnabled is set back.
/// </summary>
public string OriginalButtonText { get; set; }
/// <summary>
/// Gets or sets the loading button text.
/// </summary>
/// <value>The loading button text.</value>
public string LoadingButtonText { get; set; }
/// <summary>
/// Gets or sets a value indicating whether [change button text].
/// </summary>
/// <value><c>true</c> if [change button text]; otherwise, <c>false</c>.</value>
public bool ChangeButtonText { get; set; }
/// <summary>
/// Set this to true when the operation is finished.
/// </summary>
/// <value>
/// <c>true</c> if this instance is finished; otherwise, <c>false</c>.
/// </value>
public bool IsFinished
{
get { return (bool)GetValue(IsFinishedProperty); }
set
{
SetValue(IsFinishedProperty, value);
this.OnIsFinishedChanged();
}
}
/// <summary>
/// Called when [is finished change].
/// </summary>
/// <param name="value">if set to <c>true</c> [value].</param>
private void OnIsFinishedChanged()
{
if (this.AssociatedObject != null && !((Button)this.AssociatedObject).IsEnabled)
{
((Button)this.AssociatedObject).IsEnabled = true;
((Button)this.AssociatedObject).Content = this.OriginalButtonText;
}
}
// Using a DependencyProperty as the backing store for IsFinished. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsFinishedProperty =
DependencyProperty.Register("IsFinished", typeof(bool), typeof(SubmitButtonBehavior), new PropertyMetadata(false));
/// <summary>
/// Initializes a new instance of the <see cref="SubmitButtonBehavior"/> class.
/// </summary>
public SubmitButtonBehavior()
{
// defaults
this.ChangeButtonText = true;
this.LoadingButtonText = "Please Wait...";
// AssociatedObject is empty at initialization this.originalButtonText = this.AssociatedObject.Content.ToString();
}
protected override void Invoke(object parameter)
{
if (this.IsEnabled)
{
Button clickedButton = ((Button)this.AssociatedObject);
clickedButton.IsEnabled = false;
this.OriginalButtonText = clickedButton.Content.ToString();
if (this.ChangeButtonText)
{
clickedButton.Content = this.LoadingButtonText;
}
}
}
}
}
编辑:建议与禁止通过CanExecute。按钮文字仍然不会改变。此外,我仍然希望将其作为可重复使用的行为,但这也可能是一种好方法。
this.ButtonClickedCommand = new RelayCommand<Button>(
(clickedButton) =>
{
string originalText = clickedButton.Content.ToString();
this.IsSubmitting = true;
clickedButton.Content = "Please Wait...";
MessageBox.Show("Clicked");
this.IsFinishedSubmitButtonBehavior = true;
this.IsSubmitting = false;
clickedButton.Content = originalText;
},
(clickedButton) =>
{
return !this.IsSubmitting;
}
);
编辑:我发现一个很好的解决方案,使用消息传递,并补充说,作为我自己的问题的答案。
我从来没有使用过GalaSoft MVVM,但通常你可以用一些逻辑来编写命令的CanExecute部分,以确定是否可以执行一个命令,该命令也可以使用命令来启用/禁用一个按钮,具体取决于MVVM框架。我猜你需要等待,因为异步事件正在发生。如果在您的框架中可能,可能只需在命令开始时将CanExecute设置为false,并忘记一个行为。 – 2010-10-20 16:21:00
好的建议...我已经将这个尝试添加到了我的帖子中。但是,按钮文本不会更改。我是否需要通过不同的线程发送按钮文本更改和禁用代码? – Aligned 2010-10-20 16:32:21