对话框实现失败,因为它已经是另一个元素的逻辑子元素。

3

我正在尝试在WPF + PRISM + MVVM应用程序中实现对话框窗口。目前,我已经成功创建了样例服务,并且每个模块都能够使用此服务在窗口中显示任何视图,但问题是非常罕见的,我无法使其正常工作。

下面是窗口服务的合同。

public interface IUiDialogueService : IDisposable
{
    void Show<TView>(TView view) where TView : IViewModel;
}

public class UiDialogueService : IUiDialogueService, IDisposable
{
    private Window _dialogueWindow;

    #region Implementation of IUiDialogueService

    public void Show<TView>(TView view) where TView : IViewModel
    {
        _dialogueWindow = new Window
                              {
                                  SizeToContent = SizeToContent.WidthAndHeight,
                                  ResizeMode = ResizeMode.NoResize,
                                  ShowInTaskbar = false,
                                  Content = view.View
                              };
        _dialogueWindow.ShowDialog();
        _dialogueWindow = null;

    }
}

以下是我从模块中访问窗口服务的方法。

    private void OnStartWizard()
    {
        _dialogueService.Show(ServiceLocator.Current
                    .GetInstance<IOrgManagementOrganizatioSetupViewViewModel>());
    }

当我第一次打开窗口时,一切都运行良好,但是在我关闭它并在窗口内打开相同或其他视图后,我会遇到以下异常:

指定的元素已经是另一个元素的逻辑子级。请先断开连接。

以下代码引发了此异常。

        _dialogueWindow = new Window
                              {
                                  SizeToContent = SizeToContent.WidthAndHeight,
                                  ResizeMode = ResizeMode.NoResize,
                                  ShowInTaskbar = false,
                                  Content = view.View
                              };

有人能解释一下这里出了什么问题吗?在MVVM架构中有更好的获取子(dialogue)窗口的方法吗?

2个回答

3

Show的最后一行代码之前添加以下代码:

_dialogueWindow.Content = null;

Show现在应该看起来像这样:

public void Show<TView>(TView view) where TView : IViewModel
{
    _dialogueWindow = new Window
                          {
                              SizeToContent = SizeToContent.WidthAndHeight,
                              ResizeMode = ResizeMode.NoResize,
                              ShowInTaskbar = false,
                              Content = view.View
                          };
    _dialogueWindow.ShowDialog();
    _dialogueWindow.Content = null;
    _dialogueWindow = null;
}

这似乎可以工作,但这只是一个简单的实现,我无法想象如何使此窗口返回某些内容或在关闭事件上调用回调函数。您能否提供一些使用回调方法或对话框结果选项实现此场景的好例子? - Rati_Ge
如果这是您的建议,代码引发了异常,我会将您的答案标记为已回答,但请提供有关回调的更多信息。 - Rati_Ge
@Rati_Ge:我不明白回调函数与异常有什么关系。请创建一个新问题来询问回调函数 - 这对你更好,因为你更有可能得到有用的答案。如果需要,你可以链接到这个问题以提供背景信息。 - Daniel Hilgarth

1

在WPF中,每个元素只能属于一个父元素。即使元素不再显示(或不再显示),父子关系仍然存在。如果要给元素一个新的父元素,则需要首先从旧父元素中删除它。

在您的情况下,在Show()中,您正在将窗口的内容设置为您的视图。即使在显示该窗口之后,视图仍然是该窗口的子级。如果您现在尝试在不同的窗口中显示相同的视图,则会收到该异常。

最好的方法是从窗口中删除视图(在Daniel Hilgarth的答案中描述)。或者,您可以检查视图是否已经有父级,并手动从该父级中删除它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接