我现在写MVVM中的ViewModel都会把窗体传递进来如 public class MainWindowViewModel : Z.Core.WPF.NotificationObject
{
private readonly Window window;
public MainWindowViewModel(Window win)
{
this.window = win;
Init();
}
}然后在调用的地方用 public MainWindow()
{
this.DataContext = new ViewModel.MainWindowViewModel(this);
InitializeComponent();
}为什么是要这样呢?
因为我在窗体中有一个按钮是关闭当前Window的
然后我给他绑定到我的ViewModel中的命令如: public ICommand OnClose { get; set; }
public void Close(EventArgs e)
{
if (Service.ServiceClient.Instance != null)
{
Service.ServiceClient.Instance.Leave();
Service.ServiceClient.Instance.Close();
Service.ServiceClient.Instance = null;
}
//this.window.Close();
}但是这样的话在窗体里面点击关闭(不是窗口右上角的X)的时候,
只会执行我的命令内容,而不会关闭窗体(因为给程序只当他是一般命令)
然后现在我只能把窗体的对像传进来,然后在Close命令中加上
this.windows.Close()来实现关闭那正确的MVVM做法是应该怎么做谢谢
{
private readonly Window window;
public MainWindowViewModel(Window win)
{
this.window = win;
Init();
}
}然后在调用的地方用 public MainWindow()
{
this.DataContext = new ViewModel.MainWindowViewModel(this);
InitializeComponent();
}为什么是要这样呢?
因为我在窗体中有一个按钮是关闭当前Window的
然后我给他绑定到我的ViewModel中的命令如: public ICommand OnClose { get; set; }
public void Close(EventArgs e)
{
if (Service.ServiceClient.Instance != null)
{
Service.ServiceClient.Instance.Leave();
Service.ServiceClient.Instance.Close();
Service.ServiceClient.Instance = null;
}
//this.window.Close();
}但是这样的话在窗体里面点击关闭(不是窗口右上角的X)的时候,
只会执行我的命令内容,而不会关闭窗体(因为给程序只当他是一般命令)
然后现在我只能把窗体的对像传进来,然后在Close命令中加上
this.windows.Close()来实现关闭那正确的MVVM做法是应该怎么做谢谢
解决方案 »
- 请帮忙把以下参数转换为C#的...
- 热门讨论:学习C#项目实开发,书中出现源代码的缺失和相关的拼凑,造成学习上有多大困难,请各位初学者购书时注意
- 压缩文件
- 主线程一直循环OnPaint,导致内存不足!!! 可有解决办法
- 请教如何编写一个WINFORM程序的日志类,最好有实例代码
- C#中如何判断一个字符是否为中文?
- 一个开源的快速IOC容器分享
- sql08安装提示Framework3.5的问题
- .net 动态调用WCF 提供的参数不起作用 why????
- vs.net中的正则表达式
- MS chart 鼠标点在曲线上时间显示为 1899-12-30
- 请教一个关于IEnumerable的OrderBy问题
你把窗体传进去 和普通的写法无太大差异哦
通常只是view引用vm 但是vm不关心view是什么 这样才能松耦合哦
具体来时楼主可以看看事件 消息机制 mvvmlight prism 这些框架
也许会有收获 还有 切忌不要为了mvvm而mvvm
public class SomeWindow: ChildWindow
{
private SomeViewModel _someViewModel; public SomeWindow()
{
InitializeComponent(); this.Loaded += SomeWindow_Loaded;
this.Closed += SomeWindow_Closed;
} void SomeWindow_Loaded(object sender, RoutedEventArgs e)
{
_someViewModel = this.DataContext as SomeViewModel;
_someViewModel.PropertyChanged += _someViewModel_PropertyChanged;
} void SomeWindow_Closed(object sender, System.EventArgs e)
{
_someViewModel.PropertyChanged -= _someViewModel_PropertyChanged;
this.Loaded -= SomeWindow_Loaded;
this.Closed -= SomeWindow_Closed;
} void _someViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == SomeViewModel.DialogResultPropertyName)
{
this.DialogResult = _someViewModel.DialogResult;
}
}
}
用CallMehothod方法: <Button Content="关闭" Name="btnLeave" Height="23" FontSize="10">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<!-- 调用Window.Close会触发Closed事件,自动执行后台的OnClose命令 -->
<ei:CallMethodAction TargetObject="{Binding RelativeSource={RelativeSource AncestorType=Window}}" MethodName="Close" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>如果不忌讳写在code behind类中的话,可以这样: public MainWindow()
{
this.DataContext = new ViewModel.MainWindowViewModel();
InitializeComponent(); this.btnLeave.Click += (o, args) => this.Close(); // 同样会自动触发执行OnClose命令
}另外,我觉得特殊情况下,只要不违反MVVM总的原则,传个参数就传了,没什么了不起。
只不过作为构造参数传进去,ViewModel所有的地方都能访问到UI,影响太大。
可以把window作为Command的参数传过去,缩小它的作用范围: <Button Content="关闭" Name="btnLeave" Height="23" FontSize="10"
Command="{Binding OnClose}"
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=Window}}" />
后台的OnClose命令现在被两处调用(Button.Command和Window.Closed),所以要修改下: public void Close(object e)
{
// 这是从Window.Closed事件调用过来的
if (e is EventArgs)
{
if (Service.ServiceClient.Instance != null)
{
Service.ServiceClient.Instance.Leave();
Service.ServiceClient.Instance.Close();
Service.ServiceClient.Instance = null;
}
}
else if (e is Window) // 这是从Button.Command事件调用过来的
(e as Window).Close(); // 这里会再自动触发Window.Closed事件
}
上面这种做法不能让正统的MVVM人士看到,因为不够纯正。