2011-03-24 86 views
0

Laurent,将确认对话框添加到EventToCommand

当用户选择按钮来执行操作时,常见的期望行为是在执行该操作之前显示确认对话框。当此行为与视图模型一起处理时,需要大量管道来实现此目的。由于这种行为可能被严格视为GUI问题,因此我想要设计一种允许视图处理确认对话框的方法。

因此,我从您的EventToCommand类继承并创建了EventToCommandWithConfirm。这个类调用了一个我不打算包含的自定义消息框视图,但我想获得关于这个概念的反馈,以及它是否可以被认为包含在你的工具箱中。

using System; 
using System.Windows; 
using System.Windows.Input; 
using System.Windows.Interactivity; 

namespace GalaSoft.MvvmLight.Command 
{ 
    public partial class EventToCommandWithConfirm : EventToCommand 
    { 

     protected override void Invoke(object parameter) 
     { 
      // if confirmation is not required, the command can be run immediately 
      if (!IsConfirm) 
      { 
       base.Invoke(parameter); 
      } 
      else 
      { 
       switch (ConfirmButtons) 
       { 
        case MessageBoxPopUp.Buttons.YesNo: 
        case MessageBoxPopUp.Buttons.YesNoCancel: 
         MessageBoxPopUp.Show(ConfirmMessage, ConfirmCaption , ConfirmButtons, YesAction:() => base.Invoke(parameter)); 
         break; 
        case MessageBoxPopUp.Buttons.Ok: 
        case MessageBoxPopUp.Buttons.OkCancel: 
        case MessageBoxPopUp.Buttons.None: 
        default: 
         MessageBoxPopUp.Show(ConfirmMessage, ConfirmCaption, ConfirmButtons, OKAction:() => base.Invoke(parameter)); 
         break; 
       } 

      }    
     } 

     public static readonly DependencyProperty IsConfirmProperty = DependencyProperty.Register("Confirm", typeof(bool), typeof(EventToCommandWithConfirm), null); 
     public bool IsConfirm 
     { 
      get { return (bool)GetValue(IsConfirmProperty); } 
      set { SetValue(IsConfirmProperty, value); } 
     } 

     public static readonly DependencyProperty ConfirmCaptionProperty = DependencyProperty.Register("ConfirmCaption", typeof(string), typeof(EventToCommandWithConfirm), null); 
     public string ConfirmCaption 
     { 
      get { return (string)GetValue(ConfirmCaptionProperty); } 
      set { SetValue(ConfirmCaptionProperty, value); } 
     } 

     public static readonly DependencyProperty ConfirmMessageProperty = DependencyProperty.Register("ConfirmMessage", typeof(string), typeof(EventToCommandWithConfirm), null); 
     public string ConfirmMessage 
     { 
      get { return (string)GetValue(ConfirmMessageProperty); } 
      set { SetValue(ConfirmMessageProperty, value); } 
     } 

     public static readonly DependencyProperty ConfirmButtonsProperty = DependencyProperty.Register("ConfirmButtons", typeof(MessageBoxPopUp.Buttons), typeof(EventToCommandWithConfirm), null); 
     public MessageBoxPopUp.Buttons ConfirmButtons 
     { 
      get { return (MessageBoxPopUp.Buttons)GetValue(ConfirmButtonsProperty); } 
      set { SetValue(ConfirmButtonsProperty, value); } 
     } 
    } 
} 

使用例:

<Button Content="Delete Room..." Height="36" HorizontalAlignment="Left" Margin="279.838,237,0,0" Name="DeleteRoomButton" VerticalAlignment="Top" Width="92" Grid.Column="2"> 
      <i:Interaction.Triggers> 
       <i:EventTrigger EventName="Click"> 
        <confirm:EventToCommandWithConfirm Command="{Binding DeleteRoomClick}" MustToggleIsEnabled="True" ConfirmMessage="{Binding cvsRooms.View.CurrentItem.Description}" ConfirmCaption="Delete Room?" IsConfirm="True" ConfirmButtons="YesNoCancel"/> 
       </i:EventTrigger> 
      </i:Interaction.Triggers> 
</Button> 

MessageBoxPopUp.xaml.cs

using System; 
using System.Windows; 
using System.Windows.Controls; 
using System.Collections.Generic; 

namespace GalaSoft.MvvmLight.Command 
{ 

    public partial class MessageBoxPopUp : ChildWindow 
    { 

     public enum Buttons 
     { 
      Ok, 
      YesNo, 
      OkCancel, 
      YesNoCancel, 
      None, 
     } 

     public enum ButtonTypes 
     { 
      Ok, 
      Yes, 
      No, 
      Cancel, 
      Custom, 
     } 


     private int _buttonCount = 0; 
     private Dictionary<int, Button> _buttons = new Dictionary<int, Button>(); 
     private int _defaultButtonIdx = Int32.MinValue; 
     private Action _defaultAction = null; 
     private Button _defaultButton = null; 

     public string Message 
     { 
      get { return MessageTextBlock.Text; } 
      set { MessageTextBlock.Text = value; } 
     } 

     public ButtonTypes DefaultButton {get;set;} 
     public ButtonTypes ResultButton {get; private set;} 
     public int ButtonSelectedIdx { get; private set; } 


     public MessageBoxPopUp() 
     { 
      InitializeComponent(); 
     } 

     /// <summary> 
     /// Displays a message box with the specified text, caption, buttons 
     /// </summary> 
     /// <param name="Message">The text to display in the message box.</param> 
     /// <param name="Caption">he text to display in the title bar of the message box.</param> 
     /// <param name="Buttons">The set of buttons to display</param> 
     /// <param name="DefaultButton">Which button is the default</param> 
     /// <param name="Width">Width of the message box</param> 
     /// <param name="Height">Height of the message box</param> 
     /// <param name="Opacity">Opacity of the message box</param> 
     /// <param name="OKAction">Action to perform when the OK button is selected</param> 
     /// <param name="CancelAction">Action to perform when the Cancel button is selected</param> 
     /// <param name="YesAction">Action to perform when the Yes button is selected</param> 
     /// <param name="NoAction">Action to perform when the No button is selected</param> 
     /// <param name="MessageBoxToUse">Optional pre-configured instance of window to use. Use only if custom results are required.</param> 
     /// <param name="CustomButton">Any number of custom pairs of button names and associated actions if selected</param> 
     public static void Show(String Message, String Caption = "", Buttons Buttons = Buttons.None, ButtonTypes DefaultButton = ButtonTypes.Ok, double Width = Int32.MinValue, double Height = Int32.MinValue, double Opacity = Int32.MinValue, Action OKAction = null, Action CancelAction = null, Action YesAction = null, Action NoAction = null, MessageBoxPopUp MessageBoxToUse = null, params Tuple<string, Action>[] CustomButton) 
     { 
      MessageBoxPopUp msgBox = MessageBoxToUse != null ? MessageBoxToUse : new MessageBoxPopUp(); 
      msgBox.ResultButton = ButtonTypes.Cancel; 
      if (Width != Int32.MinValue) 
       msgBox.Width = Width; 
      if (Width != Int32.MinValue) 
       msgBox.Height = Height; 
      if (Width != Int32.MinValue) 
       msgBox.Opacity = Opacity; 
      msgBox.Title = Caption; 
      msgBox.Message = Message; 
      msgBox.ButtonSelectedIdx = -1; 


      // create the stock buttons 
      if (Buttons == Buttons.Ok || Buttons == Buttons.OkCancel) 
       msgBox.CreateButton("Ok",() => { msgBox.ResultButton = ButtonTypes.Ok; if (OKAction != null) msgBox.Closed += (s, e) => OKAction.Invoke(); msgBox.DialogResult = true; }, DefaultButton == ButtonTypes.Ok); 
      if (Buttons == Buttons.YesNo || Buttons == Buttons.YesNoCancel) 
       msgBox.CreateButton("Yes",() => { msgBox.ResultButton = ButtonTypes.Yes; if (YesAction != null) msgBox.Closed += (s, e) => YesAction.Invoke(); msgBox.DialogResult = true; }, DefaultButton == ButtonTypes.Yes); 
      if (Buttons == Buttons.YesNo || Buttons == Buttons.YesNoCancel) 
       msgBox.CreateButton("No",() => { msgBox.ResultButton = ButtonTypes.No; if (NoAction != null) msgBox.Closed += (s, e) => NoAction.Invoke(); msgBox.DialogResult = false; }, DefaultButton == ButtonTypes.No); 
      if (Buttons == Buttons.YesNoCancel || Buttons == Buttons.OkCancel) 
       msgBox.CreateButton("Cancel",() => { msgBox.ResultButton = ButtonTypes.Cancel; if (CancelAction != null) msgBox.Closed += (s, e) => CancelAction.Invoke(); msgBox.DialogResult = false; }, DefaultButton == ButtonTypes.Cancel); 
      if (CustomButton != null) 
      { 
       foreach (Tuple<string, Action> custom in CustomButton) 
       { 
        msgBox.CreateButton(custom.Item1,() => { msgBox.ResultButton = ButtonTypes.Custom; if (custom.Item2 != null) msgBox.Closed += (s, e) => custom.Item2.Invoke(); msgBox.DialogResult = true; }, msgBox._buttons.Count == 0); 
       } 
      } 

      // add the buttons to the grid 
      resetAndClearGrid(msgBox.ButtonsGrid); 
      addColumnDefinitionsToGrid(msgBox.ButtonsGrid, msgBox._buttons.Count); 
      for (int i = 0; i < msgBox._buttons.Count; i++) 
      { 
       addButtonToGrid(msgBox.ButtonsGrid, msgBox._buttons[i], i); 
      } 
      if (msgBox._defaultButton != null) 
       msgBox._defaultButton.Focus(); 

      msgBox.Show(); 
     } 


     private static void resetAndClearGrid(Grid grid) 
     { 
      grid.Children.Clear(); 
      grid.ColumnDefinitions.Clear(); 
     } 

     private static void addColumnDefinitionsToGrid(Grid grid, int columns) 
     { 
      for (var i = 0; i < columns; i++) 
      { grid.ColumnDefinitions.Add(new ColumnDefinition()); } 
     } 

     private static void addButtonToGrid(Panel grid, UIElement button, int columnIndex) 
     { 
      grid.Children.Add(button); 
      button.SetValue(Grid.ColumnProperty, columnIndex); 
     } 

     private void CreateButton(String ButtonText, Action ButtonAction, bool IsDefaultButton) 
     { 
      Button _newButton = new Button 
      { 
       Content = ButtonText, 
       Margin = new Thickness(2) 
      }; 
      int thisButtonIdx = _buttons.Count; 
      Action doAction =() => { ButtonSelectedIdx = thisButtonIdx; ButtonAction.Invoke(); }; 

      _newButton.Click += (sender, args) => 
       doAction.Invoke(); 
      _buttons.Add(_buttonCount++, _newButton); 
      if (IsDefaultButton) 
      { 
       _defaultButton = _newButton; 
       _defaultAction = doAction; 
      } 
     } 

    } 
} 

回答

0

我看到了一些积极的和你的想法有些消极。积极的一点是,需要更少的“管道”。否定的是MessageBoxPopUp不可配置。

在MIX11中,我将介绍一种显示对话框的方式,我认为这种对话框更加灵活。我一直在多个WP7应用程序和Silverlight应用程序中使用它,并且它工作得很好。它确实有点“管道”,但它很灵活,易于测试(我将在MIX中展示它是如何的),并且可以装配在一个组件中以供重用。

干杯, 洛朗

+0

洛朗, 我期待着在4月份的MIX11演示。我不会在拉斯维加斯,但我会尽快观看视频。我们喜欢看你以前的所有视频。 我得到你说的对话框不能被配置为通用。我实际上使窗口高度可配置,但没有完全暴露给EventToCommandWithConfirm类。可以添加其他参数以公开更多功能。我已经发布了上面的消息框的代码来展示我的意思。 – tsdude 2011-03-25 18:21:35

+0

你能指出这个例子吗? – Jeff 2011-11-08 02:08:02