C# 如何在WPF中使用MVVM从另一个视图打开一个视图
我是MVVM的新手。很长一段时间以来,我一直无法得到这个问题的答案。我不知道这个问题是这么难还是我解释得不好。我有MainWindow.Xaml,它包含一个textblock和一个从textblock接收数据的按钮,现在当我按下一个按钮时,它应该会打开第二个名为tableView.Xaml的视图(我已经为它/Xaml创建了用户控件) 我现在有两个问题(请注意,我在回答时正在关注MVVM)? (1) 如何通过关闭当前打开的MainWindow.xaml表单(此按钮单击使用MVVM绑定),从按钮单击打开此视图“tableView.xaml” 我的新表单必须打开的按钮单击代码(通过关闭当前的MainWindow.xaml)在这里(因此我猜打开tableView.xaml的代码只能在这里的某个地方): 此stp必须转到tableView.xaml,并且必须呈现4个stackpanel,每个stackpanel包含textblock 1)您的确切要求仍然不清楚,这使得回答这个问题非常困难。您说要“关闭当前的MainWindow.xaml表单”,但似乎表明tableView是用户控件。您是否试图关闭MainWindow并用完全不同的窗口替换它?如果是这样,那有什么意义呢?如果原始主窗口正在关闭,为什么不更改该窗口的内容 2) 这是一个很重要的话题,您必须再次提供更多关于您正试图做什么的信息,但通常您使用数据模板。首先声明要创建的GUI元素的视图模型,以及包含这些元素列表的父VM:C# 如何在WPF中使用MVVM从另一个视图打开一个视图,c#,wpf,xaml,mvvm,valueconverter,C#,Wpf,Xaml,Mvvm,Valueconverter,我是MVVM的新手。很长一段时间以来,我一直无法得到这个问题的答案。我不知道这个问题是这么难还是我解释得不好。我有MainWindow.Xaml,它包含一个textblock和一个从textblock接收数据的按钮,现在当我按下一个按钮时,它应该会打开第二个名为tableView.Xaml的视图(我已经为它/Xaml创建了用户控件) 我现在有两个问题(请注意,我在回答时正在关注MVVM)? (1) 如何通过关闭当前打开的MainWindow.xaml表单(此按钮单击使用MVVM绑定),从按钮单击
public abstract class GuiItem { } // base class
public class TextBlockVM : GuiItem { }
public class CheckBoxVM : GuiItem { }
public class TextBoxVM : GuiItem { }
public class CustomViewModel : ViewModelBase
{
private GuiItem[] _GuiItems = new GuiItem[]
{
new TextBlockVM{},
new CheckBoxVM{},
new TextBoxVM{}
};
public GuiItem[] GuiItems { get { return this._GuiItems; } }
}
然后创建ItemsControl,将ItemsSource绑定到阵列,指定要在其上绘制它们的面板类型,并包含指定如何在GUI中为每个VM设置模板的DataTemplates:
<ItemsControl ItemsSource="{Binding GuiItems}" Margin="10">
<ItemsControl.Resources>
<DataTemplate DataType="{x:Type local:TextBlockVM}">
<TextBlock Text="This is a TextBlock" />
</DataTemplate>
<DataTemplate DataType="{x:Type local:CheckBoxVM}">
<CheckBox>This is a CheckBox</CheckBox>
</DataTemplate>
<DataTemplate DataType="{x:Type local:TextBoxVM}">
<TextBox Width="100" HorizontalAlignment="Left"/>
</DataTemplate>
</ItemsControl.Resources>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
这是一个复选框
结果:
显然,这是一个非常简单的示例,只是为了说明总体思路,在现实世界的应用程序中,您还需要向视图模型添加字段,以指定文本和命令处理程序等。好的,首先,您应该定义应用程序的导航系统。它是主窗口还是子窗口?它是有书页的框架吗?是带标签的主窗口吗?然后创建将覆盖此逻辑的类 例如,要从viewmodel显示子窗口并向其传递一些输入,可以执行以下操作:
public class MainWindowViewModel
{
private IDialogService _dialogService;
public MainWindowViewModel(IDialogService dialogService)
{
_dialogService = dialogService;
SaveCommand = new DelegateCommand(Save);
}
//implement PropertyChanged if needed
public string SomeInput { get; set; }
public DelegateCommand SaveCommand { get; private set; }
private void Save()
{
var tableViewModel = new TableViewModel();
tableViewModel.SomeInput = this.SomeInput;
_dialogService.ShowModal(new DialogOptions
{
Title = "Table view",
Content = tableViewModel
});
}
}
如果您需要导航到另一个页面而不是打开新窗口,则可以轻松创建NavigationService而不是DialogService。想法是一样的
为什么我不直接在viewmodel中创建子窗口?因为窗口是视图,我想保持关注点的分离
为什么我要使用IDialogService
而不是具体的类?MVVM原则之一是可测试性。在运行时,将使用打开真实窗口的具体类,但在测试中,我可以轻松创建不会打开窗口的mock
通常,如果要从viewmodel关闭窗口,请在viewmodel中创建并调用某些事件(例如CloseRequested),窗口应侦听该事件:
public class MainWindowViewModel
{
public event EventHandler CloseRequested;
private void Close()
{
var closeRequested = CloseRequested;
if (closeRequested != null) closeRequested (this, EventArgs.Empty);
}
}
//mainwinow.xaml.cs
public MainWindow()
{
InitializeComponent();
var viewModel = new MainWindowViewModel();
viewModel.CloseRequested += (sender, args) => this.Close();
DataContext = viewModel;
}
我相信纯MVVM对您来说有点太难了,而且设计得太过复杂了。你可能无法充分利用它 让我们结合MVVM和经典方法来简化它: 创建MainWindow.xaml、MainWindowViewModel、TableView.xaml和TableViewModel:
public class MainWindowViewModel
{
//implement INotifyPropertyChanged if needed
public int NumberOfRows { get; set; }
public int NumberOfColumns { get; set; }
public void Save()
{
//do something if needed
}
}
MainWindow.xaml:
<StackPanel>
<TextBlock Text="Rows" />
<TextBox Text="{Binding NumberOfRows}" />
<TextBlock Text="Columns" />
<TextBox Text="{Binding NumberOfColumns}" />
<Button Content="Save" Click="Save_Click" />
</StackPanel>
TableView.xaml.cs
public partial class TableView: Window
{
public TableView(int rows, int colums)
{
InitializeComponent();
DataContext = new TableViewModel();
//do whatever needed with rows and columns parameters.
//You will probably need then in TableViewModel
}
TableViewModel ViewModel
{
get { return (TableViewModel )DataContext; }
}
}
通常,应用程序中存在不应关闭的主WinOW。例如,导航系统,如带有框架的主窗口,承载Page1、Page2等,或打开子窗口和对话框的主窗口。我没有使用任何内置的MVVM库,如(MVVM light或Prism)。如何获取此“DialogOptions”和“IDialogService”?请编辑问题。为了我要做的,我也没有使用任何图书馆。我已经创建了自己的IDialogService接口和实现。基本上,它只是一个简单的类,根据指定的参数显示窗口。@DialoService,不是内置的吗?但它提供了未知的接口。。在代码中执行此操作时缺少库或引用。但请阅读编辑部分的代码,即使它适合我的scenaro?IDialogService是我自己的界面。在您的场景中,您可以定义IDialogService.SwitchWindows(..)方法请编辑问题。对于我试图做的事情,TableView.xaml缺失,请解释在何处编写c#代码以生成GUI,该GUI将呈现给TableView.xaml。以及如何编写tableView.xaml,使其能够呈现通过c#代码传递给它的GUI?我无法为您编写整个应用程序。问题是关于打开窗口和传递参数。视图生成可以在TableView.xaml.cs中完成,也可以通过将datagring等控件绑定到viewmodel来完成。如果你不知道如何回答,就提出新问题。
<StackPanel>
<TextBlock Text="Rows" />
<TextBox Text="{Binding NumberOfRows}" />
<TextBlock Text="Columns" />
<TextBox Text="{Binding NumberOfColumns}" />
<Button Content="Save" Click="Save_Click" />
</StackPanel>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new MainWindowViewModel();
}
MainWindowViewModel ViewModel
{
get { return (MainWindowViewModel)DataContext; }
}
private void Save_Click(object sender, RoutedEventArgs e)
{
ViewModel.Save();
var tableViewWindow = new TableView(ViewModel.NumberOfRows, ViewModel.NumberOfColumns);
this.Close();
tableViewWindow.Show();
}
}
public partial class TableView: Window
{
public TableView(int rows, int colums)
{
InitializeComponent();
DataContext = new TableViewModel();
//do whatever needed with rows and columns parameters.
//You will probably need then in TableViewModel
}
TableViewModel ViewModel
{
get { return (TableViewModel )DataContext; }
}
}