我正在尝试实现WPF表单关闭的MVVM模式,这在本博客中也有解释,我正在获得系统。当我试图在关闭按钮命令上设置对话框结果时,InvalidOperationException错误信息"只有在创建窗口并显示为对话框后才能设置对话框结果":
DialogResult = true;
这是我的ViewModel:
class MainWindowViewModel:INotifyPropertyChanged
{
private bool? dialogResult;
public bool? DialogResult
{
get { return dialogResult; }
set
{
if (value != this.dialogResult)
{
this.dialogResult = value;
OnPropertyChanged("DialogResult");
}
}
}
public string Text
{
get { return "Hello!"; }
}
void CloseCommandExecute()
{
this.DialogResult = true;
}
和
<Window x:Class="WpfApplication.Mvvm.Windowclosing.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication.Mvvm.Windowclosing"
local:DialogCloser.DialogResult="{Binding DialogResult}"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainWindowViewModel />
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<TextBlock Text="{Binding Text}" Grid.Row="0"/>
<Button Grid.Row="1" Command="{Binding CloseCommand}">Close Me</Button>
</Grid>
</Window>
我在这里做错了什么?
设置对话框结果仅在使用ShowDialog()打开表单时有效。当您尝试在使用Show()打开的表单上设置对话框结果时,会得到此错误。
我在创建一个通过ShowDialog()
调用的窗口时遇到了这个问题。在窗口中,我有一个Ok_Clicked
,它包含了一堆语句。为了"保证"对话框返回false,如果有任何错误,我首先将DialogResult
初始化为false。如果一切都是正确的,那么我将DialogResult
设置为true并关闭窗口。我一直得到相同的异常。
我了解到,如果DialogResult
未设置为true, ShowDialog
将始终返回false。当我在Ok_Clicked
的开头删除DialogResult = false
时,我不再得到异常。
我想到了另一个可能对别人有帮助的答案。在设置对话sult之前,我最终在窗口上调用Close()。请确保不要这样做,否则将导致此错误。
对于使用ShowDialog的用户,您可以从按钮中删除属性:
IsCancel = true和 IsDefault = true
我知道这个线程已经很老了,但今天我遇到了同样的问题。我做错的是,我用ShowDialog()
打开了一个新窗口,而不是用Close()
关闭了新窗口,并试图将dialgresult设置为True。
但是它已经足够了,如果你只设置对话sult为True,之后窗口将自动关闭,没有必要调用Close()
方法。
由于绑定,您试图过早设置Window.DialogResult
。假设您的DialogCloser.DialogResult
(您没有向我们展示)实现也将DialogResult
设置在Window
上。尝试将绑定模式更改为OneWayToSource
,以便更改仅传播到您的VM,而不是其他方式:
local:DialogCloser.DialogResult="{Binding DialogResult, Mode=OneWayToSource}"
或者也许这只是一个问题,改变你的行为,只有设置Window.DialogResult
,如果Window
已经显示为一个对话框。没有看到一切很难说。
我得到这个错误,并通过在单击事件处理程序中的任何其他代码之前设置dialgresult来解决它。当它结束时,就在Close之前,我就会得到错误。但在一开始,它是有效的。
我有
IsDefault="True"
在上定义多个按钮。
我遇到了同样的问题,使用ShowDialog()并在调用close之前设置结果。
我所做的就是在设置结果之前隐藏对话框。所以,当设置对话sult的可见性必须设置为可见,隐藏和折叠都会给你一个误导性的错误,"对话sult只能在窗口创建并显示为对话框后设置。"
对于我来说,像Jarvis一样,这个错误是由于在调用Close()之后为通过ShowDialog()显示的窗口设置了dialgresult而引起的。
在我的情况下,我认为这是因为我正在将代码从WinForms移植到WPF。这个顺序在WinForms中工作得很好,但是WPF不喜欢它。
我尝试了其他的修复,比如从我的按钮中删除isDefault和isCancel属性,但这些都没有效果。
我的方法是将对话框作为Close Me按钮的命令参数传递。这种方法是在Galasoft MVVM Light Toolkit的帮助下完成的。
首先,您应该通过添加这段代码 来定义您的窗口名称x:Name="mainWindow"
然后设置mainWindow"作为Close Me按钮命令的命令参数。
<Window x:Class="WpfApplication.Mvvm.Windowclosing.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication.Mvvm.Windowclosing"
x:Name="mainWindow"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainWindowViewModel />
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100"/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<TextBlock Text="{Binding Text}" Grid.Row="0"/>
<Button Grid.Row="1"
Command="{Binding CloseCommand}"
CommandParameter="{Binding ElementName=mainWindow}">Close Me</Button>
</Grid>
在视图模型中,更新CloseCommandExecute()以包含Window作为其参数,并根据该参数设置dialgresult的值
void CloseCommandExecute(Window window)
{
window.DialogResult = true;
}
命令属性如下所示:
private ICommand _btnCloseMeCmd;
public ICommand CloseMeCmd
{
get
{
if (_btnCloseMeCmd== null)
{
_btnCloseMeCmd= new RelayCommand<Window>(CloseCommandExecute, null);
}
return _btnCloseMeCmd;
}
}
不要忘记在视图模型中添加using GalaSoft.MvvmLight.Command;
。