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

C# MVVM Xamarin从ViewModel打开新窗口-如何消除对视图的引用,c#,mvvm,xamarin.forms,C#,Mvvm,Xamarin.forms,我想在Xamarin表单应用程序中使用MVVM模式打开一个新的模式窗口。我已经研究过用MVVM模式打开一个新窗口,这让我走了这么远,但是Xamarin窗体中的windows需要一个对当前页面(视图)的引用才能从中打开一个新窗口(新视图)。这迫使我将对当前页面(视图)的引用从我的viewModel传递到我的窗口工厂,以便从中启动新窗口。这违反了MVVM。我的目标是消除viewModel中对视图的任何引用。这是我的问题,我该怎么做?我这里的代码恰好是一个模式窗口,但是普通窗口也需要一个对它从中启动的

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

窗口工厂(查看CreateNewWindow方法):

打开新模式窗口的ViewModel(请特别查看AddTask命令):

公共类BackLogViewModel:INotifyPropertyChanged
{
私人IWindowFactory m_windowFactory;
公共无效DoOpenNewWindow()
{
m_windowFactory.CreateNewWindow();
}
公共ObservableCollection AllMyStories{get;set;}
私有字符串\u已更新;
公共字符串已更新
{
得到
{
返回-更新;
}
设置
{
_更新=价值;
OnPropertyChanged();
}
}
公共网页mypage;
公共背景视图模型(第页)
{
Updated=DateTime.Now.ToString();
mypage=第页;
AllMyStories=新的ObservableCollection();
}
公共ICommand保存
{
得到{
返回新命令(()=>{
Updated=DateTime.Now.ToString();
});
}
}
公共ICommand AddTask
{
得到{
返回新命令(()=>{
m_windowFactory=新产品windowFactory(此,mypage);
DoOpenNewWindow();
});
}
}
公共事件属性更改事件处理程序属性更改;
私有void OnPropertyChanged([CallerMemberName]字符串propertyName=null)
{
var handler=PropertyChanged;
if(处理程序!=null)
{
处理程序(这是新的PropertyChangedEventArgs(propertyName));
}
}
私有命令selectCmd;
公共命令选择{
得到{
this.selectCmd=this.selectCmd??新命令(p=>
{
var-monkey=p作为故事;
if(monkey==null)返回;
第z页=新视图。故事页(p);
mypage.Navigation.PushAsync(z);
}
);
返回this.selectCmd;
}
}
}
}
如何在viewModel中删除对当前页面(视图)的引用?

我发现

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

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