MVVM Xamarin 从 ViewModel 打开新窗口 - 如何消除对视图的引用

本文关键字:何消 引用 视图 窗口 ViewModel Xamarin 新窗口 MVVM | 更新日期: 2023-09-27 18:36:00

我想在 Xamarin 窗体应用中使用 MVVM 模式打开一个新的模式窗口。我已经研究了使用 MVVM 模式打开一个新窗口,这让我走到了这一步,但是关于 Xamarin 窗体中的窗口的事情是,它们需要引用当前页面(视图)才能打开新窗口(新视图)。这迫使我将对当前页面(视图)的引用从我的视图模型传递到我的窗口工厂,以启动新窗口。这违反了 MVVM。我的目标是从我的视图模型中摆脱对视图的任何引用。这是我的问题,我该怎么做?我这里的代码恰好是一个模式窗口,但普通窗口也需要引用它启动的页面。这是我的代码,你会明白我的意思:

Window

Factory(查看 CreateNewWindow 方法):

public interface IWindowFactory
    {
        void CreateNewWindow();
    }
    public class ProductionWindowFactory: IWindowFactory
    {
        Page launchFromPage;
        BackLogViewModel viewModel;
        public ProductionWindowFactory(BackLogViewModel ViewModel, Page page)
        {
            viewModel = ViewModel;
            launchFromPage = page;
        }
        public void CreateNewWindow()
        {
            AddStoryPage window = new AddStoryPage (new AddStoryViewModel (viewModel));
            launchFromPage.Navigation.PushModalAsync (window);
        }
    }
}

打开一个新模式窗口的视图模型(特别是 AddTask 命令):

public class BackLogViewModel : INotifyPropertyChanged
    {
        private IWindowFactory m_windowFactory;
        public void DoOpenNewWindow()
        {
            m_windowFactory.CreateNewWindow();
        }
        public ObservableCollection<Story> AllMyStories { get; set; }
        private string _updated;
        public string Updated
        {
            get 
            {
                return _updated;
            }
            set 
            {
                _updated = value;
                OnPropertyChanged ();
            }
        }
        public Page mypage;
        public BackLogViewModel (Page page)
        {
            Updated = DateTime.Now.ToString();
            mypage = page;
            AllMyStories = new ObservableCollection<Story> ();
        }
        public ICommand Save
        {
            get {
                return new Command (() => {
                    Updated = DateTime.Now.ToString();
                });
            }
        }
        public ICommand AddTask
        {
            get {
                return new Command ( () => {
                    m_windowFactory = new ProductionWindowFactory(this, mypage);
                    DoOpenNewWindow();
                });
            }
        }
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            var handler = PropertyChanged;
            if (handler != null) 
            {
                handler(this, new PropertyChangedEventArgs (propertyName));
            }
        }
        private Command selectCmd;
        public Command Select {
            get {
                this.selectCmd = this.selectCmd ?? new Command<Story>(p => 
                    {
                        var monkey = p as Story;
                        if (monkey == null) return;
                        Page z = new Views.StoryPage(p);
                        mypage.Navigation.PushAsync(z);
                    }
                );
                return this.selectCmd;
            }
        }
    }
}

如何摆脱对视图模型中当前页面(视图)的引用?

MVVM Xamarin 从 ViewModel 打开新窗口 - 如何消除对视图的引用

我后来找到了这个关于从 Xamarin 中的 ViewModel 导航视图的教程

它基本上做了我已经在做的事情,但它没有将完整视图传递给 ViewModel,而是只传递视图的 INavigation 接口,并使用它进行导航。它指出可以说它违反了 MVVM,但我怀疑它的态度是"就这样吧",因为没有明显和简单的替代方案存在。可能有一些替代方案不引用 ViewModel 中视图的任何部分,但为了继续前进,我选择了这个简单的解决方案。我保留了我的窗口工厂,以便不指定要在 ViewModel 中构建的具体窗口。