65.9K
CodeProject 正在变化。 阅读更多。
Home

Silverlight: VM、MVVM 的简单弹出窗口行为

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.97/5 (16投票s)

2010 年 8 月 10 日

Ms-PL

5分钟阅读

viewsIcon

109177

downloadIcon

670

一个简单的弹出行为,关闭时运行一些 ICommands

Haruhiro Isowa 创建,Michael Washington 协助的 Behavior。

引言

本文将介绍如何使用我的弹出窗口行为,该行为将启动一个简单的是/否Popup,并解释其工作原理,以便您可以根据需要进行调整。这个Popup应该通过为您生成Popup来简化 MVVM / VM 样式的Popup创建,从而节省您为Popup创建视图视图模型的时间,并消除了其他解决方案中所示的复杂性(例如使用消息传递/服务等)。这还允许设计人员在等待程序员为他们创建视图VM时对Popup进行一些控制。

HisowaSimplePopUpBehavior 的作用

这是它生成的Popup,但您可以通过修改代码或通过行为的属性来自定义。

sample\

这些是属性。(杂项下的所有属性都是可绑定的)。

Properties

  • Brush用于设置ButtonPopUp窗口的背景,渐变、图像等都可以。
  • CustomParameter: object,您将其传递给行为,当PopUp关闭时,它将返回给您。您可以传递选定的对象或 ID 等。
  • PopUpMessage: string,设置PopUp的消息
  • PopUpNoMessage: string,设置按钮上的文本
  • PopUpYesMessage: string,设置按钮上的文本
  • ReturnDialogResult: bool?,公开PopUp结果(您可以使用双向绑定将结果传回。我用它来设置checkbox上的IsChecked)。
  • ReturnICommand: ICommand,当PopUp关闭时运行的命令。它将传递一个dataholderHisowaSimplePopUpBehaviorResult,该类包含DialogResult (bool?), PopupDataContext(在此 Popup Behavior 版本中可能不会使用),以及InputParameter,即您在上面设置的CustomParameter

通过行为属性,您大概可以猜到会发生什么。这个Behavior将生成一个简单的Popup,您可以设置文本背景值;传入一个参数(可能用于放置相关对象);允许您绑定PopUpDialogResult;最重要的是,当PopUp关闭时运行一个ICommand,并将DialogResultDataContext以及您传入的参数传递给您,以便您的ICommand可以消费它。

使用我的 HisowaSimplePopUpBehavior

首先打开一个新的 Silverlight 应用程序。将其命名为SimplePopUpBehaviorSample。将我的HisowaSimplePopUpBehavior类添加到您的解决方案中。添加对System.Windows.InteractivitySystem.Windows.Controls的引用。System.Windows.InteractivtyBlend SDK中。构建您的项目,然后在Expression Blend中打开您的MainPage.xaml

在我们开始之前,我们需要有一个视图视图模型。在Blend中删除MainPage.xaml。通过右键单击项目并选择添加新项来向项目添加一个新项。在对话框中,设置带视图模型的用户控件,将文件命名为MainPage.xaml

New Vm

打开MainPage.xaml

将一个按钮拖到页面上。然后查找我的行为HisowaSimplePopUpBehavior并将其拖到Button上。

.behavior

现在构建并在Blend中运行它。您现在应该会看到一个简单的Popup。此时,它还没有做什么特别的事情。

ViewModel 代码

我们需要在ViewModel中设置一些代码。但在我们开始之前,我们将使用 John Papa 的DelegateCommand.cs文件。从John Papa 的 Delegate Command获取。

MainPageModel.cs代码替换为以下内容

using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Data;
using System.ComponentModel;
using System.Windows.Input;
using HisowaPopUpBehaviors;

namespace SimplePopUpBehaviorSample
{
    public class MainPageModel : INotifyPropertyChanged
    {
        public MainPageModel()
        {
            PopupSimpleResultCommand = new DelegateCommand
            (PopupSimpleResult, CanPopupSimpleResult);
        }

        #region PopupSimpleResultCommand
        public ICommand PopupSimpleResultCommand { get; set; }
        public void PopupSimpleResult(object param)
        {
            //cast to my DataContainer
            HisowaSimplePopUpBehaviorResult _result = 
            (HisowaSimplePopUpBehaviorResult)param;

            //get the dialogResult
            PopUpResult = _result.DialogResult;

            //get the input if exists
            if (_result.InputParameter != null)
            {
                Message = _result.InputParameter.ToString();
            }
        }

        private bool CanPopupSimpleResult(object param)
        {
            return true;
        }
        #endregion

        #region PopUpResult
        private bool? _PopUpResult;
        public bool? PopUpResult
        {
            get
            {
                return _PopUpResult;
            }
            set
            {
                _PopUpResult = value;
                this.NotifyPropertyChanged("PopUpResult");
            }
        }
        #endregion

        #region Message
        private string _Message;
        public string Message
        {
            get { return _Message; }
            private set
            {
                if (Message == value)
                {
                    return;
                }
                _Message = value;
                this.NotifyPropertyChanged("Message");
            }
        }
        #endregion

        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
        #endregion
    }
}

这是一个简单的VM,它有一个ICommand,该命令将Popup结果设置为属性(string Message, bool? PopupResult)。它还实现了INotifyPropertyChanged

*注意:如果您使用的项目名称不同,您可能需要修复命名空间。

现在构建,然后回到Blend

使用行为 part2,附带属性

现在我们已经完成了所有基础工作,我们可以开始充分利用HisowaSimplePopUpBehavior了。

首先,我们需要为此演示创建一个类似的 UI。

UI

使用元素属性绑定绑定这些文本值。

  • PopUpMessage: 您的消息TextboxText属性
  • PopUpYes/NoMessage: 您的TextboxText属性
  • CustomParameter: 您的输入TextboxText属性(允许对象,可以是任何内容)

elemntbind

ReturnDialogResult绑定CheckboxIsChecked属性,双向绑定

two

构建运行。现在您应该能够更改TextBox中的文本为您在textbox中输入的内容。如果popup是由按钮关闭的,则CheckBox应该被选中。

sample

应该看起来像这样。

现在我们要设置ReturnICommand,这是Behavior最重要的部分。为此,将ReturnIcommand数据绑定PopUpSimpleResultCommand构建

icom - Click to enlarge image

要检查它是否正常工作,请回到Visual Studio并在您绑定的ICommand中的某个地方设置一个断点。然后在Visual Studio调试

deb

请注意,Icommand正在接收HisowaPopUpBehaviors类,该类包含DialogResultInputParameterCustomParameter)和DataContext您可以在您的ICommand中利用这些。

我的行为解释

在本节中,我将解释行为的代码。其中大部分是依赖项属性,允许databinding,所以我会跳过它们。

这是Invoke方法,当触发器被触发时调用。

#region Invoke

        //Shows popup on event trigger you set in designer

        protected override void Invoke(object parameter)
        {
            ChildWindow _childWindow = new ChildWindow();
            _grid = new Grid();

            _grid.Width = 300;
            _grid.Height = 100;

            //width 3 cols
            _grid.ColumnDefinitions.Add(new ColumnDefinition() 
        { Width = new GridLength(1, GridUnitType.Star) });
            _grid.ColumnDefinitions.Add(new ColumnDefinition() 
        { Width = new GridLength(1, GridUnitType.Star) });
            _grid.ColumnDefinitions.Add(new ColumnDefinition() 
        { Width = new GridLength(1, GridUnitType.Star) });

            //height 3 rows
            _grid.RowDefinitions.Add(new RowDefinition() 
        { Height = new GridLength(1, GridUnitType.Star) });
            _grid.RowDefinitions.Add(new RowDefinition());
            _grid.RowDefinitions.Add(new RowDefinition());

            //add message
            TextBlock tbkMessage = new TextBlock();
            tbkMessage.Text = PopUpMessage;
            tbkMessage.SetValue(Grid.RowProperty, 0);
            tbkMessage.SetValue(Grid.ColumnProperty, 0);
            tbkMessage.SetValue(Grid.ColumnSpanProperty, 3);

            _grid.Children.Add(tbkMessage);

            //add Yes button
            Button btnYes = new Button();
            btnYes.Content = PopUpYesMessage;
            btnYes.SetValue(Grid.ColumnProperty, 0);
            btnYes.SetValue(Grid.RowProperty, 1);
            btnYes.Name = "btnYes";
            btnYes.Click += new RoutedEventHandler(btnYes_Click);

            _grid.Children.Add(btnYes);

            //add No Button
            Button btnNo = new Button();
            btnNo.Content = PopUpNoMessage;
            btnNo.SetValue(Grid.ColumnProperty, 2);
            btnNo.SetValue(Grid.RowProperty, 1);
            btnNo.Name = "btnNo";
            btnNo.Click += new RoutedEventHandler(btnNo_Click);

            _grid.Children.Add(btnNo);

            //style
            _grid.Background = BackGroundColorParameter;
            btnYes.Background = YesColorParameter;
            btnNo.Background = NoColorParameter;

            //Make it a PopUp
            _childWindow.Content = _grid;

            PopUp = _childWindow;

            PopUp.Closing += new EventHandler(PopUp_Closing);

            PopUp.Show();

        }

        #endregion    

基本上,它会创建UI,设置事件处理程序,并分配行为中的属性,例如背景消息。这是您需要调整以更改 UI 的地方。

现在是是/否按钮事件处理代码。

#region BtnClicks

        void btnNo_Click(object sender, RoutedEventArgs e)
        {
            RemoveButtonHandlers();
            PopUp.DialogResult = false;
        }

        void btnYes_Click(object sender, RoutedEventArgs e)
        {
            RemoveButtonHandlers();
            PopUp.DialogResult = true;
        }

        private void RemoveButtonHandlers()
        {
            Button btnYes = (Button)_grid.FindName("btnYes");
            btnYes.Click -= new RoutedEventHandler(btnYes_Click);

            Button btnNo = (Button)_grid.FindName("btnNo");
            btnNo.Click -= new RoutedEventHandler(btnNo_Click);
        }

        #endregion

这会设置DialogResults,同时关闭PopUp,并移除事件处理程序

现在是PopUpClosing事件的代码

#region ChildwindowClosing

        //Runs an Icommand when the Popup is closing
        //you can change what it passes to Icommand to whatever you like
        //be sure that your method can consume them


        void PopUp_Closing(object sender, CancelEventArgs e)
        {
            PopUp.Closing -= new EventHandler(PopUp_Closing);

            ReturnDialogResultCommand = PopUp.DialogResult;

            if (ReturnICommand != null)
            {
                HisowaSimplePopUpBehaviorResult _result = 
			new HisowaSimplePopUpBehaviorResult();
                _result.DialogResult = PopUp.DialogResult;
                _result.DataContext = PopUp.DataContext;
                _result.InputParameter = CustomParameter;

                ReturnICommand.Execute(_result);
            }
        }

        #endregion

这一切只是移除处理程序,从依赖项属性获取Icommand,创建我的数据容器HisowaSimplePopUpBehaviorResult,然后运行Icommand并传递HisowaSimplePopUpBehaviorResult

最后,DataContainer HisowaSimplePopUpBehaviorResult类,它在同一个文件中。

public class HisowaSimplePopUpBehaviorResult
    {
        public bool? DialogResult { get; set; }
        public object DataContext { get; set; }
        public object InputParameter { get; set; }
    }

这只是一个简单的数据持有者。

完整代码

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interactivity;
using System.ComponentModel;
using System.Reflection;

namespace HisowaPopUpBehaviors
{
    [System.ComponentModel.Description("Launches a Simple Popup on Event Trigger")]
    public class HisowaSimplePopUpBehavior : TargetedTriggerAction<frameworkelement />, 
    INotifyPropertyChanged
    {
        private ChildWindow PopUp;
        Grid _grid = new Grid();

        //constructor
        public HisowaSimplePopUpBehavior()
        { }

        #region CustomParameterProperty
        public static readonly DependencyProperty CustomParameterProperty = 
    DependencyProperty.Register("CustomParameter", typeof(object), 
    typeof(HisowaSimplePopUpBehavior), null);

        public object CustomParameter
        {
            get
            {
                return base.GetValue(CustomParameterProperty);
            }
            set
            {
                base.SetValue(CustomParameterProperty, value);
            }
        } 
        #endregion

        #region ReturnDialogResultCommandProperty

        public static readonly DependencyProperty ReturnDialogResultCommandProperty = 
    DependencyProperty.Register("ReturnDialogResultCommand", typeof(bool?), 
    typeof(HisowaSimplePopUpBehavior), null);

        public bool? ReturnDialogResultCommand
        {
            get
            {
                return (bool?)base.GetValue(ReturnDialogResultCommandProperty);
            }
            set
            {
                base.SetValue(ReturnDialogResultCommandProperty, value);
                this.NotifyPropertyChanged("ReturnDialogResultCommand");
            }
        }
        #endregion

        #region ReturnICommandProperty

        public static readonly DependencyProperty ReturnICommandProperty = 
    DependencyProperty.Register("ReturnICommand", typeof(ICommand), 
    typeof(HisowaSimplePopUpBehavior), null);

        public ICommand ReturnICommand
        {
            get
            {
                return (ICommand)base.GetValue(ReturnICommandProperty);
            }
            set
            {
                base.SetValue(ReturnICommandProperty, value);
            }
        }
        #endregion

        #region PopUpMessageProperty

        public static readonly DependencyProperty PopUpMessageProperty = 
    DependencyProperty.Register("PopUpMessage", typeof(string), 
    typeof(HisowaSimplePopUpBehavior), null);

        public string PopUpMessage
        {
            get
            {
                if (base.GetValue(PopUpMessageProperty) == null)
                {
                    return "Are you sure?";
                }
                else
                {
                    return (string)base.GetValue(PopUpMessageProperty);
                }
            }
            set
            {
                base.SetValue(PopUpMessageProperty, value);
            }
        }

        #endregion

        #region PopUpYesMessageProperty

        public static readonly DependencyProperty PopUpYesMessageProperty = 
    DependencyProperty.Register("PopUpYesMessage", typeof(string), 
    typeof(HisowaSimplePopUpBehavior), null);

        public string PopUpYesMessage
        {
            get
            {
                if (base.GetValue(PopUpYesMessageProperty) == null)
                {
                    return "Yes";
                }
                else
                {
                    return (string)base.GetValue(PopUpYesMessageProperty);
                }
            }
            set
            {
                base.SetValue(PopUpYesMessageProperty, value);
            }
        }

        #endregion

        #region PopUpNoMessageProperty

        public static readonly DependencyProperty PopUpNoMessageProperty = 
    DependencyProperty.Register("PopUpNoMessage", typeof(string), 
    typeof(HisowaSimplePopUpBehavior), null);

        public string PopUpNoMessage
        {
            get
            {
                if (base.GetValue(PopUpNoMessageProperty) == null)
                {
                    return "No";
                }
                else
                {
                    return (string)base.GetValue(PopUpNoMessageProperty);
                }
            }
            set
            {
                base.SetValue(PopUpNoMessageProperty, value);
            }
        }

        #endregion

        #region BackgroundColor
        public static readonly DependencyProperty BackGroundColorParameterProperty = 
    DependencyProperty.Register("BackGroundColorParameter", 
    typeof(System.Windows.Media.Brush), typeof(HisowaSimplePopUpBehavior), null);

        public System.Windows.Media.Brush BackGroundColorParameter
        {
            get
            {
                return (System.Windows.Media.Brush)base.GetValue
            (BackGroundColorParameterProperty);
            }
            set
            {
                base.SetValue(BackGroundColorParameterProperty, value);
            }
        }
        #endregion

        #region YesColor
        public static readonly DependencyProperty YesColorParameterProperty = 
    DependencyProperty.Register("YesColorParameter", 
    typeof(System.Windows.Media.Brush), typeof(HisowaSimplePopUpBehavior), null);

        public System.Windows.Media.Brush YesColorParameter
        {
            get
            {
                return (System.Windows.Media.Brush)base.GetValue
            (YesColorParameterProperty);
            }
            set
            {
                base.SetValue(YesColorParameterProperty, value);
            }
        }
        #endregion

        #region NoColor
        public static readonly DependencyProperty NoColorParameterProperty = 
    DependencyProperty.Register("NoColorParameter", 
    typeof(System.Windows.Media.Brush), typeof(HisowaSimplePopUpBehavior), null);

        public System.Windows.Media.Brush NoColorParameter
        {
            get
            {
                return 
		(System.Windows.Media.Brush)base.GetValue(NoColorParameterProperty);
            }
            set
            {
                base.SetValue(NoColorParameterProperty, value);
            }
        }
        #endregion

        #region Invoke

        //Shows popup on event trigger you set in designer

        protected override void Invoke(object parameter)
        {
            ChildWindow _childWindow = new ChildWindow();
            _grid = new Grid();

            _grid.Width = 300;
            _grid.Height = 100;

            //width 3 cols
            _grid.ColumnDefinitions.Add(new ColumnDefinition() 
        { Width = new GridLength(1, GridUnitType.Star) });
            _grid.ColumnDefinitions.Add(new ColumnDefinition() 
        { Width = new GridLength(1, GridUnitType.Star) });
            _grid.ColumnDefinitions.Add(new ColumnDefinition() 
        { Width = new GridLength(1, GridUnitType.Star) });

            //height 3 rows
            _grid.RowDefinitions.Add(new RowDefinition() 
        { Height = new GridLength(1, GridUnitType.Star) });
            _grid.RowDefinitions.Add(new RowDefinition());
            _grid.RowDefinitions.Add(new RowDefinition());

            //add message
            TextBlock tbkMessage = new TextBlock();
            tbkMessage.Text = PopUpMessage;
            tbkMessage.SetValue(Grid.RowProperty, 0);
            tbkMessage.SetValue(Grid.ColumnProperty, 0);
            tbkMessage.SetValue(Grid.ColumnSpanProperty, 3);

            _grid.Children.Add(tbkMessage);

            //add Yes button
            Button btnYes = new Button();
            btnYes.Content = PopUpYesMessage;
            btnYes.SetValue(Grid.ColumnProperty, 0);
            btnYes.SetValue(Grid.RowProperty, 1);
            btnYes.Name = "btnYes";
            btnYes.Click += new RoutedEventHandler(btnYes_Click);

            _grid.Children.Add(btnYes);

            //add No Button
            Button btnNo = new Button();
            btnNo.Content = PopUpNoMessage;
            btnNo.SetValue(Grid.ColumnProperty, 2);
            btnNo.SetValue(Grid.RowProperty, 1);
            btnNo.Name = "btnNo";
            btnNo.Click += new RoutedEventHandler(btnNo_Click);

            _grid.Children.Add(btnNo);

            //style
            _grid.Background = BackGroundColorParameter;
            btnYes.Background = YesColorParameter;
            btnNo.Background = NoColorParameter;

            //Make it a PopUp
            _childWindow.Content = _grid;

            PopUp = _childWindow;

            PopUp.Closing += new EventHandler(PopUp_Closing);

            PopUp.Show();
        }

        #endregion

        #region BtnClicks

        void btnNo_Click(object sender, RoutedEventArgs e)
        {
            RemoveButtonHandlers();
            PopUp.DialogResult = false;
        }

        void btnYes_Click(object sender, RoutedEventArgs e)
        {
            RemoveButtonHandlers();
            PopUp.DialogResult = true;
        }

        private void RemoveButtonHandlers()
        {
            Button btnYes = (Button)_grid.FindName("btnYes");
            btnYes.Click -= new RoutedEventHandler(btnYes_Click);

            Button btnNo = (Button)_grid.FindName("btnNo");
            btnNo.Click -= new RoutedEventHandler(btnNo_Click);
        }

        #endregion

        #region ChildwindowClosing

        //Runs an Icommand when the Popup is closing
        //you can change what it passes to Icommand to whatever you like
        //be sure that your method can consume them


        void PopUp_Closing(object sender, CancelEventArgs e)
        {
            PopUp.Closing -= new EventHandler(PopUp_Closing);

            ReturnDialogResultCommand = PopUp.DialogResult;

            if (ReturnICommand != null)
            {
                HisowaSimplePopUpBehaviorResult _result = 
            new HisowaSimplePopUpBehaviorResult();
                _result.DialogResult = PopUp.DialogResult;
                _result.DataContext = PopUp.DataContext;
                _result.InputParameter = CustomParameter;

                ReturnICommand.Execute(_result);
            }
        }

        #endregion

        // Utility

        #region INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(String info)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(info));
            }
        }
        #endregion
    }

    public class HisowaSimplePopUpBehaviorResult
    {
        public bool? DialogResult { get; set; }
        public object DataContext { get; set; }
        public object InputParameter { get; set; }
    }
} 

另请参阅: HisowaModPopUpBehavior

此变体允许您使用自己的视图和视图模型并将其注入popup

© . All rights reserved.