实现wpf中模式对话框

系统环境

本程序基于.net4.0,引入了mvvmlight轻量级框架。

Dialog类库

Dialog类库中包含3个文件

1.DialogView:

DialogView是一个自定义用户控件,在一个Grid中包含了2个Border:

第一个Border用于遮罩modal Dialog后面的地方

第二个Border是显示内容的地方将配置

VerticalAlignment="Center" HorizontalAlignment="Center"

使得显示内容居中在此Border中通过2层border实现了Dialog的圆角效果。

在内层Border内定义一个Grid,Grid拆分成2个Row,第一个Row中设置Title及关闭按钮;第二个Row显示被设置的窗体内容。

窗体内容为一个ContentControl通过DataBind来显示填充窗体内容。具体代码如下:

<Grid Visibility="{Binding Visibility}">
        <Border Background="White" Opacity="{Binding Opcity}"></Border>
        <Border VerticalAlignment="Center" HorizontalAlignment="Center">
            <Border BorderThickness="1" BorderBrush="#34629E" Width="{Binding Width}" Height="{Binding Height}" CornerRadius="3">
                <Border BorderThickness="1" BorderBrush="#9ACAFF" Background="#DAE7FA" CornerRadius="3">
                    <Grid>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="25"></RowDefinition>
                            <RowDefinition Height="*"></RowDefinition>
                        </Grid.RowDefinitions>
                        <DockPanel Background="#057ABB" Grid.Row="0">
                            <Button DockPanel.Dock="Right" Margin="0,-8, 10, 0" Command="{Binding CloseCommand}">
                                <Button.Style>
                                    <Style TargetType="Button">
                                        <Style.Triggers>
                                            <Trigger Property="IsMouseOver" Value="True">
                                                <Setter Property="Template">
                                                    <Setter.Value>
                                                        <ControlTemplate>
                                                            <Image Source="/Resources/Images/Dialog_Base_Close_Over.png" 
                                               Width="46" Height="19" DockPanel.Dock="Right" >
                                                            </Image>
                                                        </ControlTemplate>
                                                    </Setter.Value>
                                                </Setter>
                                            </Trigger>
                                        </Style.Triggers>
                                        <Setter Property="FocusVisualStyle">
                                            <Setter.Value>
                                                <Style></Style>
                                            </Setter.Value>
                                        </Setter>
                                        <Setter Property="Template">
                                            <Setter.Value>
                                                <ControlTemplate>
                                                    <Image Source="/Resources/Images/Dialog_Base_Close_Normal.png" 
                                               Width="46" Height="19" DockPanel.Dock="Right" >
                                                    </Image>
                                                </ControlTemplate>
                                            </Setter.Value>
                                        </Setter>
                                    </Style>
                                </Button.Style>
                            </Button>
                            <Border VerticalAlignment="Center" DockPanel.Dock="Left">
                                <Image Source="/Resources/Images/Dialog_Title.png" Width="18" Height="13"  Margin="5,0"></Image>
                            </Border>
                            <Border DockPanel.Dock="Left" VerticalAlignment="Center">
                                <TextBlock Text="{Binding Title}" Foreground="White" FontSize="13"></TextBlock>
                            </Border>
                        </DockPanel>
                        <Grid Grid.Row="1">
                            <ContentControl Content="{Binding Content}"></ContentControl>
                        </Grid>
                    </Grid>
                </Border>
            </Border>
        </Border>
    </Grid>

 

2.DialogParam:

DialogParam中定义了窗体的5个基本属性

Opcity:控制透明度(0.0-1.0之间)

Title:窗体标题

Width:窗体宽度

Height:窗体高度

Content:窗体内容,为自定义ViewModel

    public class DialogParam
    {
        public double Opcity { get; set; }
        public string Title { get; set; }
        public object Content { get; set; }
        public int Height { get; set; }
        public int Width { get; set; }
    }

 

3.DialogViewModel:

DialogViewModel包含了DialogParam中的窗体的基本属性,用于Dialog中的绑定

Visibility:控制是否显示窗体

在DialogViewModel中使用了MvvmLight中的消息机制。注册了2个消息用token “Dialog_Open” 和 “Dialog_Close” 区分。

打开窗口消息:传入DialogParam对象,设置窗口属性及内容。

关闭窗口消息:通知消息,设置窗体不可用,并将窗体正文dispose。

代码如下:

 public class DialogViewModel : ViewModelBase, IDisposable
    {
        #region Properties
        private string _visibility = "Collapsed";
        public string Visibility
        {
            set { _visibility = value; RaisePropertyChanged("Visibility"); }
            get { return _visibility; }
        }

        private double _opcity;
        private double _defaultOpcity = 0.5;
        public double Opcity
        {
            set { _opcity = value; RaisePropertyChanged("Opcity"); }
            get { return _opcity; }
        }

        private string _title { get; set; }
        public string Title
        {
            set { _title = value; RaisePropertyChanged("Title"); }
            get { return _title; }
        }

        private int _defaultWidth = 500;
        private int _defaultHeight = 300;
        private int _width;
        public int Width
        {
            set { _width = value; RaisePropertyChanged("Width"); }
            get { return _width; }
        }

        private int _height;
        public int Height
        {
            set { _height = value; RaisePropertyChanged("Height"); }
            get { return _height; }
        }

        private object _content { get; set; }
        public object Content
        {
            get { return _content; }
            set { _content = value; RaisePropertyChanged("Content"); }
        }

        #endregion

        public RelayCommand OKCommand { get; set; }
        public RelayCommand CloseCommand { get; set; }

        /// <summary>
        /// Initializes a new instance of the DialogViewModel class.
        /// </summary>
        public DialogViewModel()
        {
            //Messenger.Default.Send(
            Messenger.Default.Register<DialogParam>(this, Constants.Dialog_Open, m =>
            {
                Visibility = "Visible";
                Opcity = m.Opcity != 0 ? m.Opcity : _defaultOpcity;
                Height = m.Height != 0 ? m.Height : _defaultHeight;
                Width = m.Width != 0 ? m.Width : _defaultWidth;
                Title = m.Title;
                Content = m.Content;
            });

            Messenger.Default.Register<NotificationMessage>(this, Constants.Dialog_Close, m =>
            {
                Visibility = "Collapsed";
                ((ViewModelBase)Content).Dispose();
            });

            CloseCommand = new RelayCommand(() =>
            {
                Visibility = "Collapsed";
                ((ViewModelBase)Content).Dispose();
            });
        }

        public void Dispose()
        {
            Messenger.Default.Unregister<NotificationMessage>(this);
            Messenger.Default.Unregister<DialogParam>(this);
        }

    }
 

测试窗体

1.主窗体

 
模式窗体处在窗口的最前面并遮罩其后面的所有内容,所以需要再主窗体MainWindow中增加DialogView并为其绑定DialogViewModel
    <Grid>
        <vw:BoardView DataContext="{Binding Board}"></vw:BoardView>
        <dialogvw:DialogView DataContext="{Binding Dialog}"></dialogvw:DialogView>
    </Grid>

在MainViewModel中创建一个DialogViewModel对象,用于绑定DialogView及接收窗口消息。

 

2.两个测试窗体

定义两个测试窗口ADialogView和BDialogView,在其对应的ViewModel中定义保存和取消命令的响应方法,在保存命令的响应方法中触发保存事件并发出关闭按钮。而取消命令只发送保存按钮。

public class ADialogViewModel : ViewModelBase
    {
        public delegate void SaveHandler();
        public event SaveHandler SaveEvent;

        public RelayCommand SaveCommand { get; set; }
        public RelayCommand CancelCommand { get; set; }

        /// <summary>
        /// Initializes a new instance of the ADialogViewModel class.
        /// </summary>
        public ADialogViewModel()
        {
            SaveCommand = new RelayCommand(() =>
            {
                if (SaveEvent != null)
                {
                    SaveEvent();
                }
                Messenger.Default.Send<NotificationMessage>(new NotificationMessage(this, ""), Constants.Dialog_Close);
                
            });

            CancelCommand = new RelayCommand(() =>
            {
                Messenger.Default.Send<NotificationMessage>(new NotificationMessage(this, ""), Constants.Dialog_Close);
            });
        }
    }

 

在资源文件中定义2个DataTemplate,DataType为ADialogViewModel和BDialogView,其内容分别为ADialog和BDialog:

        <DataTemplate DataType="{x:Type dialogvm:ADialogViewModel}">
            <dialogvw:ADialogView></dialogvw:ADialogView>
        </DataTemplate>
      
        <DataTemplate DataType="{x:Type dialogvm:BDialogViewModel}">
            <dialogvw:BDialogView></dialogvw:BDialogView>
        </DataTemplate>

 

3.主界面

BoardView是程序主界面内容,包含于主窗体中,其内定义了2个Button用于触发打开窗口的消息,在其对应的BoardViewModel中定义了两个RelayCommand,在其响应事件中设置DialogParam并发送打开窗口的消息。

如下代码所示,在响应事件中注册了SaveEvent事件的方法并配置了窗体的显示参数,最后发出打开窗口的消息。

            ShowACommand = new RelayCommand(() =>
            {
                ADialogViewModel a = new ADialogViewModel();
                a.SaveEvent += refreshBoardAfterA;
                DialogParam param = new DialogParam();
                param.Content = a;
                param.Title = "A";
                param.Height = 200;
                param.Width = 200;
                param.Opcity = 0.8;

                Messenger.Default.Send<DialogParam>(param, Constants.Dialog_Open);
            });

 

源码下载:

https://files.cnblogs.com/icestone/ModalDialogDemo.zip

posted @ 2011-11-28 21:35  通灵宝玉  阅读(2988)  评论(0编辑  收藏  举报