我的问题很简单:下面的代码片段有多糟糕? 你怎么做?
CancelEventHandler _windowClosing;
private CancelEventHandler WindowClosing
{
set
{
clearEventHandlerList();
this.Closing += value;
_windowClosing = value;
/*
* if calling the method with null parameters,
* it will set up itself as the primary control on the Window
*/
_windowClosing(null,null);
}
get
{
return _windowClosing;
}
}
private readonly CancelEventHandler[] CONTROLS = null;
private int current = 0;
public InitializerForm()
{
InitializeComponent();
/*
* these are the handlers for the different controls,
* in the order of appereance to the user
*/
STATES = new CancelEventHandler[] { handler1, handler2, etc. };
WindowClosing = CONTROLS[0];
}
private void clearEventHandlerList()
{
foreach (CancelEventHandler c in CONTROLS)
{
this.Closing -= c;
}
}
private void handler1(object obj, CancelEventArgs e)
{
if (obj == null)
{
//hide every other control, but this one, also set up if necessary
}
else
{
//do something
WindowClosing = CONTROLS[++current]; // set the next control to show
e.Cancel = true;
}
}
关键是代码不会关闭表单,而是显示另一个组件,并设置处理方式(这是移动平台,因此单击顶部的OK按钮会生成关闭事件)。这是因为向用户一个接一个地显示几个表单(4或5)使得应用程序闪烁,并且也非常烦人,而更换组件则更加顺畅。这个模型有效,但看起来非常讨厌,我希望有一种更清晰的方法来处理这个问题。
更新 我更新了代码示例,以便变量名称有点说话。不过,我确信这很糟糕,(a)但不确定多少,更重要的是,(b)如何做得更好。
更新2: 所以,似乎代码仍然有点神秘。
现在问题是: 我向用户显示一个表单,指示他用多种语言做什么。他通过单击窗口上的确定继续。接下来,我问他的语言,然后问一些问题(他/她的GPS等等)。在他能够回答问题后(这不应该超过几秒钟),我向他展示了一个启动画面(我在一个单独的线程中加载东西),它有一张图片。一个接一个地显示这些表单使得整个应用程序开始变慢,并且填充了UI滞后。
这就是我要解决的问题:我将窗口的内容放入面板中,然后将这些面板放在另一个面板上,并隐藏它们中的每一个,但应隐藏给用户可见的一个。 (current
变量)每个窗口都做不同的事情,所以我需要另外更改窗口closing
事件的处理程序。在此代码中,启用面板的部分与处理窗口关闭事件的部分具有相同的功能(handler1
,handler2
等)。如果参数是null
,它会执行前者,如果不是(这意味着它是由用户触发的),它会执行后者。
我需要一个可扩展的解决方案,以便我可以随时插入和删除对话框(命令和指向函数的指针存储在CONTROLS
字段中,这似乎非常方便,如果你真的理解它。尽管改变表单的整个内容并不容易,但应该有一种更简单的方法来做到这一点,以及一个更好的方法,这就是我正在寻找的。 p>
我希望这次我可以解释模型是如何运作的。
答案 0 :(得分:2)
我认为理论上可能会让这些代码更加令人愉快地转移,危险地顽皮,令人愉快地变得危险,快乐且不真实,但这需要一些认真思考。
答案 1 :(得分:1)
如果你真的需要一些帮助,你必须先自己动手......
答案 2 :(得分:0)
使用,XML!这是人类可读的!
更严重 -
看起来你正在尝试创建某种配置向导,所以我首先要研究它。关于您的特定解决方案,我通常主张非常强烈反对“分层面板”方法。我这样做是因为我维护的应用程序是由发现这种方法的人编写的,或者是相关的“选项卡控件隐藏选项卡”方法,这是一个好主意。它不是,维护者会在未来几年诅咒你的名字。
话虽如此,有哪些替代方案?好吧,一个替代方案是你已经因为它的“闪烁”而被解雇的。我会说,一般来说,闪烁对于快速而肮脏的应用来说并不是什么大不了的事。例如,确保在关闭旧窗口之前调用新窗口可能是个好主意。 (我假设这是可能的,我还没有在移动设备上开发。)
另一种可能性可能是分层面板的恶劣版本。不是将六个面板放入一个表单中,而是为每个向导页面创建单独的用户控件,然后将用户控件添加/删除到包含的表单中。这可以避免您的闪烁,并且将证明更容易维护,因为每个页面都在不同的控件中。这也可以简化任何后续的“后退”按钮功能,并使您的数据结构更自然地定义,因为这些用户控件将与特定的逻辑数据位相关联。它仍然不理想,但对于一次性解决方案来说可能已经足够了。
第三种技术,如果您预见到扩展向导修改随着产品的成熟,可能会通过以更逻辑/声明的方式定义用户控件来概括用户控件的创建(例如,通过XML) 。如果您基于XML动态生成合理的控件,那么修改面板可能就像潜入XML并执行以下操作一样简单:
<Questions>
<Question type="Text"> <!-- generate a textbox for the answer field -->
Favorite Color:
</Question>
<Question type="Number" range="0-255"> <!-- Maybe this is a spinner -->
The answer to life, the universe, and everything:
</Question>
</Questions>
这只是我的头脑, 完全 过度使用任何一次性应用程序,但这是可能的。
答案 3 :(得分:0)
现在,让我告诉我这可能有用,但它可能不是你真正问题的答案 - 当你有很多表格时,缓慢而无响应的用户界面。真正的答案可能是继续并执行所有单独的表单,但每个表单在用户盯着第一个表单时在后台线程中加载其子表单。
但是假设你仍然坚持这一点,我首先要创建一个单独的类来处理Panel堆叠/层次结构。称之为PanelManager。您将实例化PanelManager并将其与主窗体关联,然后向其添加Panel(可能键入String)并设置顺序。在主窗体中,让闭包处理程序调用PanelManager.CloseCurrentPanel(),如果没有更多的面板要显示,那么就该关闭主窗体了。
伪代码的时间!这是课堂上的一个简单的想法,我将留给你实现它:
public class PanelManager {
// constructor
public PanelManager (Form ownerForm);
// short-cut properties
public Panel this[int idx]
{ get; set; }
public int Index
{ get; set; }
// main functionality
public int AddPanel (Panel p);
public void SetPanelOrder (Panel p, int idx);
public void RemovePanel (Panel p);
public void RemovePanelAt (int idx);
// shows the first Panel
public void Show ();
// shows Panel[idx]
public void Show (int idx);
// adds the panel to the top of the stack and displays it
// returns the index of the panel
public int AddPanelAndShow (Panel p);
// hides the current panel, displays the one underneath it
// returns false if there are no more panels
public bool HideCurrentPanel ();
}
在主窗体的构造函数中,通过新的PanelManager(this)实例化它,然后在关闭事件处理程序中,调用panelManager.HideCurrentPanel(),然后确定是否需要在此之后关闭它。