大家好
说起子窗体,大家都会想到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>
</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>
创建ChildWindow的基类
新建类:ChildWindowActionBase 并从TriggerAction
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/
</i:Interaction.Triggers>
对之对应的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的分层思想,子窗体可以随心定制,而不需要去改逻辑层的代码。具体代码以上全部提供,谢谢。