|ZYCWPF| 在MVVM中的ViewModel,要不要把当前的Window传递进去了,如果不传的话如何在ViewModel中去关闭这个窗口 谢谢

javamy024 2012-11-08 10:04:57
我现在写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做法是应该怎么做

谢谢
...全文
577 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
心灵彩虹 2012-11-08
  • 打赏
  • 举报
回复
http://stackoverflow.com/questions/501886/wpf-mvvm-newbie-how-should-the-viewmodel-close-the-form
心灵彩虹 2012-11-08
  • 打赏
  • 举报
回复
http://stackoverflow.com/questions/501886/wpf-mvvm-newbie-how-should-the-viewmodel-close-the-form
心灵彩虹 2012-11-08
  • 打赏
  • 举报
回复

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;
        }
    }
}

lhx527099095 2012-11-08
  • 打赏
  • 举报
回复
楼主 mvvm的设计主要是为了解耦 你把窗体传进去 和普通的写法无太大差异哦 通常只是view引用vm 但是vm不关心view是什么 这样才能松耦合哦 具体来时楼主可以看看事件 消息机制 mvvmlight prism 这些框架 也许会有收获 还有 切忌不要为了mvvm而mvvm
jshi123 2012-11-08
  • 打赏
  • 举报
回复
楼上的链接里各种做法都有了。整理一下: 用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人士看到,因为不够纯正。
源码JCiOSProjectSampleWithRAC,把最近做的一个项目的业务流程剥离,只剩下可公用的项目框架,以便以后类似项目使用。 具体内容: 1、工程目录结构参考: http://limboy.me/ios/2013/09/23/build-ios-application.html 2、用CocoaPods加入一些常用、成熟的第三方库。 3、Vendors下放一些体量小,且自己可能会直接修改源码的第三方类。 4、实现一个从服务端获取内容到UI显示的过程,做成基类供不同业务继承使用。 5、实现一些常用的UI效果或者控件。(未完善...) 6、多Stroyboard和独立视图XIB混用。 6、通过重新设置AppDelegate.window的RootViewController,实现app内多种入口的切换(侧边栏抽屉与TabBarController切换)。 几个类的说明: BaseServerDataListViewModel 所有下拉刷新,拉到底部则加载更多的视图的ViewModel基类。定义一些公用的操作和属性。 例如工程的EventListViewModel就是继承自此类。 EventListViewController 由于多个地方可能用到同样的列表视图,所以将这个列表视图独立出来,由其它需使用的视图包含此视图,达到重用的目的。 例如工程的FirstFlowRootViewController包含了这个列表。 列表视图的MVVM说明: 1、EventListViewController对应EventListViewModel,除界面外的所有具体流程都在ViewModel执行,并反馈给ViewController进行界面显示。 2、EventListViewController内的tableView需显示Cell的内容,所以每个Cell对应一个Cell的ViewModel,这些Cell的ViewModel由视图的ViewMode提供。 一些备忘: 使用Mantle进行JSon数据转Model。 使用GVUserDefaults统一管理[NSUserDefaults standardUserDefaults]的值。 使用UIScrollView UzysCircularProgressPullToRefresh使TableView实现下来刷新。 使用UIScrollView JCLoadMoreIndicator是TableView实现底部加载更多。 一些常用的方法写在UtilityFunc类。 BuildPhases添加RunScirpt使编译时BuildNumber自动 1。

110,536

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧