【问题标题】:Open another window in xaml view in WPF在 WPF 的 xaml 视图中打开另一个窗口
【发布时间】:2014-01-26 01:25:46
【问题描述】:

我是 Wpf 的新手,并遵循 MVVM 模式来设计我的应用程序。我有一个 ViewModel 和一个 View。按照设计,我的 View 知道我的 ViewModel,反之则不然。如果我想在单击按钮时打开另一个窗口,我可以使用命令,当用户单击时,该命令将被路由到我的 ViewModel。

但是我将如何创建一个拥有自己的视图和 ViewModel 的窗口。我对此有点困惑。我想从 Xaml 本身调用新窗口,因为我的 ViewModel 不知道另一个视图,可能它是 viewmodel。

为了简单起见,

View1 -> (bound to) ViewModel1
View1 -> Button1.Click -> Command(bound to) ViewModel1
---- how to open View2 -> (bound to) ViewModel2------
Show View2.

谢谢

【问题讨论】:

    标签: c# wpf xaml mvvm viewmodel


    【解决方案1】:

    我只需从 View 1 的代码隐藏中调用 Show 来打开 View 2。不应涉及来自 View 1 的 ViewModel。

    像这样:

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        new View2().Show();
    }
    

    您的下一个想法可能是“这不是违反 MVVM 吗?”不,我不会这么说。如果 ViewModel 被认为是 MVVM 的干净实现,则不应直接控制 UI 元素。如果您希望 ViewModel 中的某些内容触发窗口打开,您可以随时使用事件或 Caliburn 等 3rd 方库轻松实现此功能,而无需担心耦合。

    【讨论】:

      【解决方案2】:

      这是我建议这样做的。因为在另一个视图模型中没有与视图的依赖关系。只需编写一个对话框服务来打开任何视图作为弹出(窗口)。 通常Show() 方法使用System.Windows 依赖关系,因此更好地用作服务,然后我们可以对我们的应用程序进行单元测试。

          public interface IDialogService
          {
              BaseViewModel ShowTitleDialog(BaseViewModel viewModel, UserControl view, string windowTitle);
          }
      
          public class DialogService : IDialogService
          {
              public BaseViewModel ShowTitleDialog(BaseViewModel viewModel, UserControl view, string windowTitle)
              {
                  if (view == null && viewModel == null)
                  {
                      throw new ArgumentNullException("view is null");
                  }
      
                  RegisterTemplate(viewModel.GetType(), view.GetType());
                  return ShowTitleDialog(viewModel, windowTitle);
              }
              private void RegisterTemplate(Type viewModelType, Type viewType)
              {
                  const string xamlTemplate = "<DataTemplate DataType=\"{{x:Type vm:{0}}}\"><v:{1} /></DataTemplate>";
                  var xaml = String.Format(System.Globalization.CultureInfo.InvariantCulture, xamlTemplate, viewModelType.Name, viewType.Name, viewModelType.Namespace, viewType.Namespace);
      
                  var context = new ParserContext();
      
                  context.XamlTypeMapper = new XamlTypeMapper(new string[0]);
                  context.XamlTypeMapper.AddMappingProcessingInstruction("vm", viewModelType.Namespace, viewModelType.Assembly.FullName);
                  context.XamlTypeMapper.AddMappingProcessingInstruction("v", viewType.Namespace, viewType.Assembly.FullName);
      
                  context.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
                  context.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");
                  context.XmlnsDictionary.Add("vm", "vm");
                  context.XmlnsDictionary.Add("v", "v");
      
                  var template = (DataTemplate)System.Windows.Markup.XamlReader.Parse(xaml, context);
                  var key = template.DataTemplateKey;
                  Application.Current.Resources[key] = template;
              }
      
              public BaseViewModel ShowTitleDialog(BaseViewModel viewModel, string windowTitle, bool isEnableScrollBars = false)
              {
                  Window window = new Window();
                  window.WindowStartupLocation = WindowStartupLocation.CenterScreen;
                  ContentControl contentControl = new ContentControl();
                  contentControl.Content = viewModel;
      
                  if (!isEnableScrollBars)
                  {
                      window.Content = contentControl;
                      window.SizeToContent = SizeToContent.WidthAndHeight; window.SizeToContent = SizeToContent.WidthAndHeight;
                  }
                  else
                  {
                      ScrollViewer scrollViewver = new ScrollViewer();
                      scrollViewver.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
                      scrollViewver.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
                      scrollViewver.Content = contentControl;
                      window.Height = 600;
                      window.MaxHeight = 600;
                      window.Content = scrollViewver;
                  }
      
                  window.Title = windowTitle;
                  window.WindowStyle = WindowStyle.None;
      
                  window.Owner = Application.Current.Windows.OfType<System.Windows.Window>().FirstOrDefault(x => x.IsMouseOver);
                  window.ShowInTaskbar = false;
                  window.ShowDialog();
                  return viewModel;
              }
          }
      

      用法..

          class TestAViewModel
          {
            public void ClickEvent()
            {
              TestBViewModel viewModel = new TestBViewModel();
              viewModel.ShowThisView();
            }
          }
      
          class TestBViewModel
          {
            public void ShowThisView()
            {
               TestBViewModel viewModel = new TestBViewModel();
               TestBView view = new TestBView();
               view.DataContext = viewModel;
      
               IDialogService dialogCheckIn = new DialogService();
               dialogCheckIn.ShowTitleDialog(viewModel, view, "Title");
            }
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-08-13
        • 1970-01-01
        • 1970-01-01
        • 2010-11-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多