这是一个新手问题,但我无法解决。在尝试使用SO"视图模型应如何关闭窗体"的答案时,我有一个UserControl定义为:
<UserControl
.....
h:DialogCloser.DialogResult="{Binding DialogResult}"
>
设计时显示:
Property 'DialogResult' is not attachable to elements of type 'UserControl'.
DialogCloser定义为:
public static class DialogCloser
{
public static readonly DependencyProperty DialogResultProperty =
DependencyProperty.RegisterAttached(
"DialogResult",
typeof(bool?),
typeof(DialogCloser),
new PropertyMetadata(DialogResultChanged));
private static void DialogResultChanged(
DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
var window = d as Window;
if (window != null)
window.DialogResult = e.NewValue as bool?;
}
public static void SetDialogResult(Window target, bool? value)
{
target.SetValue(DialogResultProperty, value);
}
}
UserControl由以下人员打开:
var win = new WindowDialog();
win.Title = title;
win.DataContext = datacontext;
return win.ShowDialog();
在UserControl的视图模型中,我有:
public new void DoExit()
{
DialogResult = true;
}
private bool? dialogresult;
public bool? DialogResult
{
get
{
return dialogresult;
}
set
{
if (dialogresult != value)
{
dialogresult = value;
OnPropertyChanged("DialogResult");
}
}
}
使用DoExit()时,模式对话框myUserControl不会关闭。怎么了?我如何让设计者(VS 2010)不抛出错误?
感谢您的帮助。
附录:
public class ModalDialogService : IModalDialogService
{
public bool? ShowDialog(string title, object datacontext)
{
var win = new WindowDialog();
win.Title = title;
win.DataContext = datacontext;
return win.ShowDialog();
}
}
注意:如果"UserControl"被设置为"Window",设计者会很高兴,但错误是:
"Window must be the root of the tree. Cannot add Window as a child of Visual."
帮助别人?
我对此很陌生,但综合来看,我建议这是像我这样的新手的一个可能答案。
这是否符合MVVM的最佳实践?
首先,正如设计者所说"属性"DialogResult"不可附加到"UserControl"类型的元素
我的翻译是,"控件"不是一个窗口,所以它不能关闭。因此,
h:DialogCloser.DialogResult="{Binding DialogResult}"
是错误的。移除它。
其次,我的用户控件被显示为这样一个普通窗口的唯一元素
<Window x:Class="Nova5.UI.Views.Ink.WindowDialog"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WindowDialog"
WindowStyle="SingleBorderWindow"
WindowStartupLocation="CenterOwner" SizeToContent="WidthAndHeight">
<ContentPresenter x:Name="DialogPresenter" Content="{Binding .}"/>
</Window>
现在,当最上面的视图模型进行时,整个过程就开始了
var dialog = new WindowDialog
{
Title = "It's me Margaret",
ShowInTaskbar = false,
Topmost = true,
ResizeMode = ResizeMode.NoResize
};
dialog.Owner = Application.Current.Windows.OfType<Window>().SingleOrDefault(x => x.IsActive);
ModalDialogService dialogService = new ModalDialogService();
dialogService.ShowDialog<PrescriptionWriterViewModel>(dialog,
new PrescriptionWriterViewModel(),
returnedViewModelInstance =>
{
if (dialog.DialogResult.HasValue && dialog.DialogResult.Value)
{
}
}
);
};
当在用户控件上单击Exit时,它通过其视图模型中的DelegateCommand执行
public new void DoExit()
{
OnRequestClose();
}
public event EventHandler RequestClose;
void OnRequestClose()
{
EventHandler handler = this.RequestClose;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
然后在启动对话框服务中处理关闭请求
public void ShowDialog<TDialogViewModel>(IModalWindow view, TDialogViewModel viewModel, Action<TDialogViewModel> onDialogClose)
{
view.DataContext = viewModel;
IDialogViewModel vm = viewModel as IDialogViewModel;
if (vm !=null)
vm.RequestClose += (s,e)=> view.Close(); //RequestClose is the event in the ViewModel that the view will listen for.
if (onDialogClose != null)
{
view.Closed += (sender, e) => onDialogClose(viewModel);
}
view.Show();
}
当视图关闭时,onDialogClose(viewModel)会调用回最顶层的视图模型,并完成指定的操作
returnedViewModelInstance =>
{
if (dialog.DialogResult.HasValue && dialog.DialogResult.Value)
{
}
}
这样就完成了几个小时紧张的学习。我希望它对某些人有用。