我使用MVVM创建了一个WPF应用程序,而我在关闭/打开窗口时遇到了困难。在我的登录窗口中,我使用以下方法关闭登录窗口并单击按钮打开WindowOPHome窗口:
WindowOPHome dashboard = new WindowOPHome();
dashboard.Show();
Application.Current.MainWindow.Close();
在WindowOPHome窗口打开时,一切正常,登录窗口关闭。当我尝试关闭WindowOPHome窗口并使用类似于Login Window / WindowOPHome操作的按钮单击打开WindowMainAdmin窗口时,WindowMainAdmin窗口会在一瞬间打开,然后在WindowOPHome永远不会出现时消失。以下是关闭WindowOPHome并打开WindowMainAdmin的代码:
WindowMainAdmin dashboard = new WindowMainAdmin();
dashboard.Show();
Application.Current.MainWindow.Close();
任何帮助将不胜感激!如果您需要任何其他代码,请告诉我。非常感谢你!
答案 0 :(得分:4)
我建议您明确关闭要关闭的窗口,而不是假设它是当前的主窗口。
使用MVVM有很多不同的方法,您可以使用附加行为或通过命令参数将窗口传递给视图模型,如下所示:
按钮xaml中的视图:
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
在视图模型中的命令execute方法中:
if (parameter is System.Windows.Window)
{
WindowMainAdmin dashboard = new WindowMainAdmin();
dashboard.Show();
(parameter as System.Windows.Window).Close();
}
。
或者,您可以迭代所有窗口,直到找到所需的窗口。
foreach( Window window in Application.Current.Windows ) {
if(window is WindowOPHome)
{
window.Close();
break;
}
}
如果您需要打开多个窗口实例,则可能需要检查其他一些属性,而不仅仅是关闭该类型的第一个属性。
您甚至可以将其调整为每个窗口类中的静态关闭方法。
答案 1 :(得分:1)
我认为在创建管理员窗口时,程序会将您的管理员窗口视为当前主窗口并关闭它。为避免这种情况,您可以显式关闭所需的窗口。我建议实现一个MainViewModel来管理你的所有窗口。此示例假定您只想打开一个窗口。
在视图(任何窗口)中:
private void OnClose(object sender, RoutedEventArgs e)
{
//ICommand Implemnation that informs MainViewModel of UserInput
//In this case, the command ShowOPHome is an Enum
inputhandler.Execute(MyCommands.ShowOPHome);
}
在ViewModel中:
BaseWindow dashboard;
....
public void ShowWindow(MyCommands Param)
{
//Verify Parameter
....
if(!(dashboard is null))
dashboard.Close();
switch(Param)
{
case MyCommands.ShowOPHome:
dashboard = new WindowOPHome();
break;
case MyCommands.ShowMainAdmin:
dashboard = new WindowMainAdmin();
break;
}
dashboard.Show();
}
InputHandler:
public class Inputhandler : ICommand
{
...
public class Execute(object Data)
{
...
mainViewModel.ShowWindow(MyCommands.ShowOPHome);
...
}
...
}
答案 2 :(得分:1)
您可以使用几个辅助类
为此问题创建MVVM纯解决方案public static class ViewCloser
{
public static readonly DependencyProperty DialogResultProperty = DependencyProperty.RegisterAttached(
"DialogResult",
typeof(bool?),
typeof(ViewCloser),
new PropertyMetadata(DialogResultChanged));
private static void DialogResultChanged(DependencyObject target, DependencyPropertyChangedEventArgs args)
{
var view = target as Window;
if (view == null)
return;
if (view.IsModal())
view.DialogResult = args.NewValue as bool?;
else
view.Close();
}
public static void SetDialogResult(Window target, bool? value)
{
target.SetValue(DialogResultProperty, value);
}
}
public static class WindowExtender
{
public static bool IsModal(this Window window)
{
var fieldInfo = typeof(Window).GetField("_showingAsDialog", BindingFlags.Instance | BindingFlags.NonPublic);
return fieldInfo != null && (bool)fieldInfo.GetValue(window);
}
}
在应用程序中,首先在ViewModel中创建一个属性
private bool? _viewClosed;
public bool? ViewClosed
{
get { return _viewClosed; }
set {
_viewClosed = value);
RaisePropertyChanged("ViewClosed");
}
}
然后使用我们的助手类在View中绑定它。
<Window x:Class="
...
vhelpers:ViewCloser.DialogResult="{Binding ViewClosed}"
...
>
答案 3 :(得分:0)
所有这些都是很好的解决方案!我选择了cjmurph的解决方案,因为它非常简单(对于我虚弱的头脑)而且我可以很容易地适应它以备将来使用。见下面的实施代码。再次感谢大家!
<强> XAML 强>
Command="{Binding BtnMainAdminPageGO}"
CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window}}"
<强> WindowOPMainViewModel 强>
private ICommand _btnMainAdminPage;
public ICommand BtnMainAdminPageGO
{
get
{
if (_btnMainAdminPage == null)
{
_btnMainAdminPage = new RelayCommand(param => this.BtnMainAdminPage(), null);
}
return _btnMainAdminPage;
}
}
private void BtnMainAdminPage()
{
WindowMainAdmin dashboard = new WindowMainAdmin();
dashboard.Show();
foreach(Window window in Application.Current.Windows)
{
if (window is WindowOPHome)
{
window.Close();
break;
}
}
}