2010-10-20 50 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將讀取並顯示正確的文本。

相關問題