2010-10-20 17 views
0

我试图建立一种行为,禁用该按钮并更改文本以遵循常见模式禁用按钮来停止用户双击。我需要行为更改在命令前生效。我能以这种方式使用行为吗?如何在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; 
      } 
      ); 

编辑:我发现一个很好的解决方案,使用消息传递,并补充说,作为我自己的问题的答案。

+1

我从来没有使用过GalaSoft MVVM,但通常你可以用一些逻辑来编写命令的CanExecute部分,以确定是否可以执行一个命令,该命令也可以使用命令来启用/禁用一个按钮,具体取决于MVVM框架。我猜你需要等待,因为异步事件正在发生。如果在您的框架中可能,可能只需在命令开始时将CanExecute设置为false,并忘记一个行为。 – 2010-10-20 16:21:00

+0

好的建议...我已经将这个尝试添加到了我的帖子中。但是,按钮文本不会更改。我是否需要通过不同的线程发送按钮文本更改和禁用代码? – Aligned 2010-10-20 16:32:21

回答

0

我发现比使用MvvmLight工具箱消息传递的行为更好的解决方案。使用在MainPage.xaml.cs中 1.创建密钥 2.寄存器在构造函数中消息的密钥

GalaSoft.MvvmLight.Extras.SL4.Messenger.Default.Register<NotificationMessage>(this, 
MainPage.EnableButtonKey, message =>{     
// send true if submitting, false if finished 
      // Save or Saving is default 
      this.SaveButton.IsEnabled = message.Content; 

this.SaveButton.Content = message.Notification; }); } ));

  1. 发送消息来启用或禁用按钮,例如:Messenger.Default.Send>(new NotificationMessage(this,false,“Please Wait ...”),MainPage。SubmitKey); //重新启用 Messenger.Default.Send>(new NotificationMessage(this,true,originalButtonText),MainPage.SubmitKey);
0

由于丹评论说,使用CanExecute来实现禁用逻辑可能会更好。至于改变按钮文本,我会推荐使用绑定到this.IsSubmitting通过ValueConverter选择正确的文本。这最大限度地减少了ViewModel和View之间的交互,因为ViewModel所做的就是说我正在提交,并且View将读取并显示正确的文本。

相关问题