如何在C#MVVM中打开其他窗口?
我有一个简单的问题: 在我的应用程序中,我有一个“mainview”/main窗口。 从这一点,用户可以控制所有的事情,如数据库查询,搜索等 但是我需要点击菜单按钮打开一个属性窗口 因此,我将它绑定到我的搜索窗口命令:如何在C#MVVM中打开其他窗口?,c#,wpf,mvvm,C#,Wpf,Mvvm,我有一个简单的问题: 在我的应用程序中,我有一个“mainview”/main窗口。 从这一点,用户可以控制所有的事情,如数据库查询,搜索等 但是我需要点击菜单按钮打开一个属性窗口 因此,我将它绑定到我的搜索窗口命令: private ICommand searchwindowcommand; public ICommand SearchWindowCommand { get { if (se
private ICommand searchwindowcommand;
public ICommand SearchWindowCommand
{
get
{
if (searchwindowcommand == null)
{
searchwindowcommand = new RelayCommand(p => ExcecuteSearchwindowcommand());
}
return searchwindowcommand;
}
}
public void ExcecuteSearchwindowcommand()
{
}
通常我会这样打开它:(我让应用程序工作,但我没有使用mvvm,现在我必须重做应用程序并计算出mvvm:)
要显示另一个窗口,我必须在Executecommand中写入什么?
我应该为另一个视图创建新的viewmodel吗?(我想是的?)
编辑:
我的Startapplikationcode:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
SetupBindings();
}
private void SetupBindings()
{
pViewModelList viewModel = new pViewModelList();
personlistview.DataContext = viewModel;
}
}
我应该为另一个视图创建新的viewmodel吗?(我想是的?)
对
我必须在我的执行命令中写入什么才能显示其他命令
窗户
在这种情况下,我通常会在ViewModel中引发一个事件。视图将处理程序附加到此事件,并且实际的ShowDialog()
在此处理程序中执行
下面是一些伪代码,展示了这个想法:
// ViewModel
public class MainViewModel
{
public event EventHandler<EventArgs<UpdateViewModel>> UpdateRequested;
private void ExecuteUpdate()
{
if (this.UpdateRequested != null)
{
var childVm = new UpdateViewModel(/* parameters related to the object being updated */);
this.UpdateRequested(this, new EventArgs<UpdateViewModel>(childVm));
}
}
}
// View
public class MainView
{
public MainView()
{
var vm = new MainViewModel();
this.DataContext = vm;
vm.UpdateRequested += (sender, e) =>
{
var updateView = new UpdateView();
updateView.DataContext = e.Data; // Gets the instance of the viewModel here
updateView.ShowDialog();
};
}
}
//视图模型
公共类主视图模型
{
公共事件事件处理程序UpdateRequested;
私有void ExecuteUpdate()
{
if(this.UpdateRequested!=null)
{
var childVm=new UpdateViewModel(/*与正在更新的对象相关的参数*/);
this.UpdateRequested(this,neweventargs(childVm));
}
}
}
//看法
公共类主视图
{
公共主视图()
{
var vm=新的MainViewModel();
this.DataContext=vm;
vm.UpdateRequested+=(发件人,e)=>
{
var updateView=new updateView();
updateView.DataContext=e.Data;//在此处获取viewModel的实例
updateView.ShowDialog();
};
}
}
实际上,为每个视图创建新的viewmodel并不是必需的。但是你应该在你的案例中创建一个新的。要从viewmodel打开新窗口,请使用中介模式,如MVVM Light的Messenger service
在ViewModel中:
Messenger.Default.Send(ViewName.PropertyWindow);
MainWindow.cs
Messenger.Default.Register<ViewName>(this, ShowPropertyWindow);
private void ShowPropertyWindow(ViewName view)
{
if(view == ViewName.PropertyWindow)
{
var propertyWindow = new PropertyWindow();
propertyWindow.DataContext = new PropertyWindowViewModel();
propertyWindow.Show();
}
}
Messenger.Default.Register(这是ShowPropertyWindow);
私有void ShowPropertyWindow(视图名称视图)
{
if(view==ViewName.PropertyWindow)
{
var propertyWindow=新的propertyWindow();
propertyWindow.DataContext=新的PropertyWindowViewModel();
propertyWindow.Show();
}
}
我目前有一个类似的要求,用户希望在另一个窗口中打开报告
我(在MVVM中)通过在窗口类的实际实例周围使用“wrapper”类完成了这项工作,重要的是,包装器构造函数被传递到窗口将要渲染的ViewModel的接口。包装器具有用于“Show”、“Close”等的方法,这些方法隐藏了实际的窗口实现类
包装类的实例由服务类创建和跟踪,该服务类了解所有打开的窗口,并且能够在应用程序关闭或用户选择从另一个ViewModel关闭窗口时关闭所有窗口
希望这有意义
视图类:
public partial class TearOffWindow : MetroWindow
{
public TearOffWindow()
{
InitializeComponent();
SourceInitialized += (s, a) => this.HideMinimizeButtons();
}
}
包装器实现:
public sealed class TearOffWindowWrapper : IWindowWrapper<TearOffWindow>
{
private readonly TearOffWindow _window;
public TearOffWindowWrapper(ITearOffViewModel viewModel)
{
_window = new TearOffWindow { DataContext = viewModel };
}
public event EventHandler Closed;
public bool IsVisible
{
get
{
return _window.Visibility == Visibility.Visible;
}
set
{
_window.Visibility = value ? Visibility.Visible : Visibility.Hidden;
}
}
public void Close()
{
_window.Close();
}
public void Show()
{
if (!_window.IsVisible)
{
_window.Closed += WindowOnClosed;
_window.Show();
_window.Activate();
}
}
public void Activate()
{
if (_window.IsVisible)
{
_window.Activate();
}
}
private void WindowOnClosed(object sender, EventArgs eventArgs)
{
_window.Closed -= WindowOnClosed;
var closed = Closed;
if (closed != null)
{
closed(this, EventArgs.Empty);
}
}
}
我是否应该为另一个视图创建新的viewmodel?(我想是的?)
这取决于您的Viewmodel以及您试图使用它执行的操作
假设您显示了一个列表
,用户可以在其中选择一个人并编辑此人。当然,您需要此模型的虚拟机,但如果它是一个列表
,则无需创建新的PersonVM
进行编辑,因为您的虚拟机应该能够处理这些事情
如何显示另一个窗口?
这只是一个简单的例子,肯定有点违反了丢失耦合的规则,因为它知道有视图,但不知道PersonV,因为PersonV是一个用户控件
public void ExcecuteSearchwindowcommand()
{
var vm = //if you need to select a VM or create a new VM
var v = new view(vm) // view is a modified Window
v.ShowDialog()
if(vm.Result)// Result will be an property which tells you
{ // how the user closed the Window e.g. Save,Cancel, ...
}
//else or whatever
}
view.cs
// this are my constructors
// obj is your vm
public DetailV(object obj)
{
InitializeComponent();
DataContext = obj;
CPresenter.Content = obj;
initializeCostumComponent();
}
// dataContext is your vm and
// content is an Usercontrol
public DetailV(object dataContext, object content)
{
InitializeComponent();
DataContext = dataContext;
CPresenter.Content = content;
initializeCostumComponent();
}
view.xaml
<Window x:Class="view"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
SizeToContent="WidthAndHeight"
WindowStartupLocation="CenterScreen"
Top="150"
DataContext="{Binding ElementName=CPresenter,Path=Content}"
Title="{Binding DisplayTitle}" Loaded="Window_Loaded" TabIndex="99999999">
<ScrollViewer Name="viewer"
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Auto">
<ScrollContentPresenter Name="CPresenter" />
</ScrollViewer>
</Window>
现在,我使用ResourceDictionary来说明特定vm的默认视图
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:NamespaceViewModel"
xmlns:vw="clr-namespace:NamespaceView">
<DataTemplate DataType="{x:Type vm:PersonVM}">
<vw:PersonV />
</DataTemplate>
</ResourceDictionary>
如果您现在有一个AdressVM,只需将它添加到您的ResourceDictionary中,它就可以工作了我同意这个事件,但我认为新的ViewModel不是强制性的。这取决于新窗口的用途。嗨!问题是,我无法引用startapplikation,因为startapplikation已经引用了我的viewmodel(用于上下文?!)现在我不知道如何创建另一个窗口类别的实例来使用ShowDialog()编辑:目的只是在appconfig中设置一些内容,没什么特别的。@Xaruth事实上这不是强制性的。但是如果视图需要绑定,我个人总是为每个视图创建一个viewModel。这只是个人偏好,因此阅读代码的人更清楚地将视图与其关联viewModel@user3793935MVVM的主要规则是:视图引用viewModels,但viewModels不引用视图。我不知道你的StartAppLike(可能在问题中提供更多代码),但无论如何viewModel不能引用视图。Uff,对不起,我有点困惑。我在问题中提供了startapplikation代码(只是数据绑定…我想我可以对另一个窗口做同样的操作,然后用我的EXECUTECOMAND调用它)Hui,这是很多只用于打开窗口的代码;(我会试试,希望能奏效:)
<Window x:Class="view"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
SizeToContent="WidthAndHeight"
WindowStartupLocation="CenterScreen"
Top="150"
DataContext="{Binding ElementName=CPresenter,Path=Content}"
Title="{Binding DisplayTitle}" Loaded="Window_Loaded" TabIndex="99999999">
<ScrollViewer Name="viewer"
VerticalScrollBarVisibility="Auto"
HorizontalScrollBarVisibility="Auto">
<ScrollContentPresenter Name="CPresenter" />
</ScrollViewer>
</Window>
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="clr-namespace:NamespaceViewModel"
xmlns:vw="clr-namespace:NamespaceView">
<DataTemplate DataType="{x:Type vm:PersonVM}">
<vw:PersonV />
</DataTemplate>
</ResourceDictionary>