[Prism]如何在主程序中合理的弹出子窗体

来源:互联网 发布:mysql配置 编辑:程序博客网 时间:2024/04/30 02:05

#以前写过的一篇博文,里面介绍的方法,在实际项目里频繁使用,分享至此


说起子窗体,大家都会想到ChildWindow,多熟悉的一个控件。不错,Sliverlight中已经提供了子窗体的具体实现,而在WPF中却没有这么好的事情(有的第三方控件商已经提供此控件)。最常见的实现方法就是在ViewModel中,直接New ChildWindow,然后直接Show。这样的方法也达到的要求。但是它不符合MVVM分层思想,再就是代码不美观,难以维护,今天我就给大家介绍一种美观又实用的方法。


原理


通过Prism中提供的InteractionRequestTrigger事件触发器,实现点击按钮或者用户的某种操作弹出对话框的效果。另外,不要忘了引用此命名空间:

using Microsoft.Practices.Prism.Interactivity.InteractionRequest;

创建ChildWindow窗体

<Window x:Class="ChildWindowDemo.ChildWindow.ChildWindow"        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"          xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"        Width="300" Height="150"         Title="{Binding Title}"        x:Name="confirmationWindow" Topmost="True" WindowStyle="ToolWindow" WindowStartupLocation="CenterScreen">    <Grid x:Name="LayoutRoot" Margin="2">        <Grid.RowDefinitions>            <RowDefinition />            <RowDefinition Height="Auto" />        </Grid.RowDefinitions>        <ContentControl HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Grid.Row="0" Content="{Binding Content}"/>        <Button Content="Cancel" Width="75" Height="23" HorizontalAlignment="Right" Margin="0,12,0,0" Grid.Row="1">            <i:Interaction.Triggers>                <i:EventTrigger EventName="Click">                    <ei:CallMethodAction TargetObject="{Binding ElementName=confirmationWindow}" MethodName="Close"/>                </i:EventTrigger>            </i:Interaction.Triggers>        </Button>        <Button Content="OK" Width="75" Height="23" HorizontalAlignment="Right" Margin="0,12,79,0" Grid.Row="1">            <i:Interaction.Triggers>                <i:EventTrigger EventName="Click">                    <ei:ChangePropertyAction PropertyName="Confirmed" TargetObject="{Binding}" Value="True"/>                    <ei:CallMethodAction TargetObject="{Binding ElementName=confirmationWindow}" MethodName="Close"/>                </i:EventTrigger>            </i:Interaction.Triggers>        </Button>    </Grid></Window>

创建ChildWindow的基类


新建类:ChildWindowActionBase 并从TriggerAction<T>派生,代码如下:

public class ChildWindowActionBase : TriggerAction<FrameworkElement>    {        protected override void Invoke(object parameter)        {            var arg = parameter as InteractionRequestedEventArgs;            if (arg == null)                return;            var windows = this.GetChildWindow(arg.Context);            var callback = arg.Callback;            EventHandler handler = null;            handler =                (o, e) =>                {                    windows.Closed -= handler;                    callback();                };            windows.Closed += handler;            windows.ShowDialog();        }        Window GetChildWindow(Notification notification)        {            var childWindow = this.CreateDefaultWindow(notification);            childWindow.DataContext = notification;            return childWindow;        }        Window CreateDefaultWindow(Notification notification)        {            return (Window)new ChildWindow.ChildWindow();        }    }   

如何调用


主程序界面代码如下:

<Window x:Class="ChildWindowDemo.MainWindow"        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"        xmlns:prism="http://www.codeplex.com/prism"        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"        xmlns:local="clr-namespace:ChildWindowDemo"        Title="MainWindow" Height="200" Width="300">    <i:Interaction.Triggers>        <prism:InteractionRequestTrigger SourceObject="{Binding ConfirmationRequest, Mode=OneWay}">            <local:ChildWindowActionBase/>        </prism:InteractionRequestTrigger>    </i:Interaction.Triggers>    <Grid>        <Button Command="{Binding RaiseConfirmation}" Content="Click Me !" HorizontalAlignment="Left" Margin="29,31,0,0" VerticalAlignment="Top" Width="217" Height="55"/>        <TextBlock HorizontalAlignment="Left" Margin="29,106,0,0" TextWrapping="Wrap" Text="{Binding ConfirmationResult}" VerticalAlignment="Top"/>    </Grid></Window>

对之对应的ViewModel:

public class MainWindowViewModel : NotificationObject    {        public MainWindowViewModel()        {            this.RaiseConfirmation = new DelegateCommand(this.OnRaiseConfirmation);            this.ConfirmationRequest = new InteractionRequest<Confirmation>();        }        public InteractionRequest<Confirmation> ConfirmationRequest { get; private set; }        public DelegateCommand RaiseConfirmation { get; private set; }        private string result;        public string ConfirmationResult        {            get { return result; }            set            {                result = value;                this.RaisePropertyChanged(() => this.ConfirmationResult);            }        }        private void OnRaiseConfirmation()        {            this.ConfirmationRequest.Raise(                new Confirmation { Content = "是否确认", Title = "子窗体" },                (cb) => { ConfirmationResult = cb.Confirmed ? "确认" : "取消"; });        }          }

总结


这样的写法比较符合MVVM的分层思想,子窗体可以随心定制,而不需要去改逻辑层的代码。具体代码以上全部提供,谢谢。

0 0
原创粉丝点击