1

情况:

我正在使用桌面组件开发 Ext.Net Web 应用程序,并且在第一次创建窗口后无法打开它。

循环从“索引”视图开始,它只是构建主桌面环境。在这个视图中,创建了一个具有 JS 处理函数的模块,如下所示:

.Modules(
     X.DesktopModule()
         .ModuleID("ModuleTitle")
         .Shortcut(
         X.DesktopShortcut()
             .Name("Module Title")
             .IconCls("custom-icon")
              .Handler("loadModuleWindow(Desktop,'AssetManager');")
  )

处理函数“loadModuleWindow”然后有责任决定是否必须第一次创建窗口,或者它已经创建并且只需要再次显示:

function loadModuleWindow(callingContainer, moduleId) {

    //Dynamically build name of script by convention       
    loadScriptFile("Scripts/" + moduleId + "Scripts.js", "js");

    //Only create new window if it hasn't been created already
    if (App[moduleId] == undefined) {
        App.direct.CreateModuleWindow(callingContainer.id, moduleId);
    } else {
        App[moduleId].show();
    }
}

当创建桌面并第一次调用模块时,将调用代码隐藏方法“CreateModuleWindow”并将窗口返回给客户端。

窗口设置为:

window.CloseAction = CloseAction.Hide;

到目前为止一切正常,问题出现在窗口关闭时(通过单击它的 [X] 关闭按钮)。正如预期的那样,该窗口从当前视图中隐藏,并且任务栏上的“指示器”也被删除。

正如您可能已经猜到的那样,使用 Handler ("loadModuleWindow") 的目的是在 Window 已经加载一次的情况下避免服务器调用。

然而,当在这个窗口上调用 Show() 方法时,会发生两件事:

1) 如果我调用不带参数的 Show() 方法,则不会发生任何事情。窗口保持隐藏状态,不再显示在桌面上。

2) 如果我调用 Show(callerContainer.id) 之类的方法给它一个目标,则窗口会显示在桌面上,但任务栏中的窗口“指示器”没有重新加载,并且我收到一条错误消息,提示“offsetWidth” " 属性未定义。

问题:

有谁知道当窗口配置为 CloseAction = Hide 以将其“恢复”到第一次创建时的桌面时可以调用的任何其他方法?

**更新:重现问题的完整代码** * ** *

入口点控制器 (DektopController.cs)

[DirectController]
public class DesktopController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    [DirectMethod(ShowMask = true)]
    public ActionResult CreateModuleWindow(string callingContainerId, string moduleId)
    {
        //Only AJAX requests are allowed
        if (Request.IsAjaxRequest() == true)
        {
            ControllerHelpers.CreateAndAttachWindow(this, callingContainerId, moduleId);
            return this.Direct();
        }
        else //No direct URL access
        { return new EmptyResult(); }
    }
}

控制器助手

    public static Window GetWindowViewModel(string moduleId)
    {
        // Dynamically instantiate the ViewModel class
        // By convention, the ViewModel that creates the Window is named
        // moduleName + "ViewModel".
        // The ViewModel should also assign the moduleId to the window.ID

        Type type = Type.GetType("App.Web.ViewModels." + moduleId + "ViewModel");

        Object obj = Activator.CreateInstance(type);

        return (Window)obj;
    }

    public static void CreateAndAttachWindow(Controller cont, string callingContainerId, string moduleId)
    {
        Desktop callingContainer = cont.GetCmp<Desktop>(callingContainerId);

        Window moduleWindow = GetWindowViewModel(moduleId);

        if (moduleWindow != null)
        {
            callingContainer.CreateWindow(moduleWindow);
        }
    }

剃刀索引文件

@model Ext.Net.Desktop

@{
   ViewBag.Title = "Desktop";
   Layout = "~/Views/Shared/_Desktop.cshtml";
   var X = Html.X();
}

@(
 X.Desktop()
    .ID("MyDesktop")
        .Listeners(l =>
        {
            l.Ready.BroadcastOnBus = "App.Desktop1.Ready";
        })
        .Modules(
            X.DesktopModule()
                .ModuleID("Module1")
                .Shortcut(
                    X.DesktopShortcut()
                        .Name("Module 1")
                        .Handler("loadModuleWindow(App.MyDesktop,'Module1');")
                )
        )
        )

"loadModuleWindow" JAVASCRIPT 文件

function loadModuleWindow(callingContainer, moduleId) {

    //Only create new window if it hasn't been created already
    if (App[moduleId] == undefined) {
        App.direct.CreateModuleWindow(callingContainer.id, moduleId);

        //Set the returned window to the module, by convention, the
        //window.id is the same as the moduleId.
        App[callingContainer.id].getModule(moduleId).setWindow(moduleId);
    } else {
        App[callingContainer.id].getModule(moduleId).run();
    }
}

MODULE1 查看模型文件

public class Module1ViewModel : Window
{
    public Toolbar TopToolBar {get; private set;}
    public TreePanel AssetHierarchy { get; private set; }

    public Module1ViewModel()
    {
        this.ID = "Module1";
        this.Title = "Module1";
        this.Width = 1400;
        this.Height = 600;
        this.Layout = LayoutType.Border.ToString();
        this.CloseAction = CloseAction.Hide;
        this.Stateful = true;
    }
}
4

1 回答 1

0

有几个问题。

首先,Module 的 id 和它的 Window 必须是唯一的,它们是独立的组件。

因此,请更改,例如,在 Module1ViewModel 中。

this.ID = "Module1_Window"

其次,桌面的 CreateWindow 显示独立于任何模块的窗口,并且 setWindow 调用不足以将窗口附加到模块。我们应该有方便的方法将一个窗口附加到一个模块,但是,目前,我们没有这样的方法。目前,我可以建议以下解决方案。

将 loadModuleWindow 函数替换为:

function loadModuleWindow(callingContainer, moduleId) {
    var module = App[callingContainer.id].getModule(moduleId);

    if (!module.win) {
        App.direct.CreateModuleWindow(moduleId, {
            success: function (result) {
                module.autoRun = true;
                module.addWindow(function () { return eval(result)[0] });
            }
        });
    } else {
        module.run();
    }
}

将 CreateModuleWindow 方法替换为:

[DirectMethod(ShowMask = true)]
public ActionResult CreateModuleWindow(string moduleId)
{
    Window moduleWindow = GetWindowViewModel(moduleId);
    moduleWindow.AutoRender = false;
    string moduleWindowCfg = ComponentLoader.ToConfig(moduleWindow);

    return this.Direct(moduleWindowCfg);
}

其余的东西不做任何更改。

关于设计的一些注意事项。

通常,桌面的模块不支持动态附加窗口,因为模块应该与其窗口一起用作不可分割的单元。这意味着模块期望为模块预定义一个窗口。它应该怎么做。您可以创建一个窗口而不将其分配给任何模块,或者您可以即时创建整个模块。

于 2013-07-02T05:26:30.020 回答