我的主要Form实例名为' MainView'并包含以下内容:
contentPanel
的面板,其中包含各种输入控件(包括childControl
,启动时禁用)。 backgroundWorker_DoWork(3-arg)
。 contentPanel
已停用,因此用户无法在处理提交内容时进行更改,垃圾邮件按钮等。如果提交成功,则还需要进行某些UI更改(下面将在“问题”部分中详细介绍)。
contentPanel相关代码
private void btnSubmit_Click(object sender, EventArgs e)
{
...
Type[] parameterTypes = new Type[] { suiteRel.GetType() };
MethodInfo method = this.GetType().GetMethod("btnSubmit_Click", parameterTypes);
mainView.backgroundWorker_DoWork(this, method, myData);
}
/// <summary>
/// Commits changes to the database.
///
/// Note: This method will be executed from a non-UI thread. As such
/// accessing or modifying UI controls must be done via an Invoke() call.
/// </summary>
public void btnSubmit_Click(Object myData)
{
...
if (success)
{
this.Invoke(new Action(
() => {
childControl.Enabled = true;
}
));
}
}
BackgroundWorker相关代码
/// <summary>
/// Starts another thread to perform a potentially long-running task (e.g. validation, database commits, etc).
/// </summary>
/// <param name="reference">
/// A reference to the control instance that owns the method to be called.
/// </param>
/// <param name="method">
/// The method to be called that will perform the work.
/// </param>
/// <param name="parameters">
/// Parameters to pass to the method when it is called.
/// </param>
public void backgroundWorker_DoWork(object reference, MethodInfo method, params object[] parameters)
{
List<object> methodAndArgs = new List<object>();
methodAndArgs.Add(reference);
methodAndArgs.Add(method);
methodAndArgs.Add(parameters);
contentPanel.Enabled = false;
this.UseWaitCursor = true;
backgroundWorker.RunWorkerAsync(methodAndArgs);
}
/// <summary>
/// Starting point of a worker thread (i.e. not on the UI thread).
/// </summary>
/// <param name="sender">
/// The object that initiated the work request.
/// </param>
/// <param name="e">
/// The arguments that dictate what work to do. In particular, e.Argument
/// contains the parameters passed to the public backgroundWorker_DoWork().
/// </param>
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
List<object> methodAndArgs = (List<object>)e.Argument;
object reference = methodAndArgs[0];
MethodInfo method = (MethodInfo)methodAndArgs[1];
object[] parameters = (object[])methodAndArgs[2];
// call method with its parameters.
// a.k.a. "method(param1, param2, ...);"
method.Invoke(reference, parameters);
}
/// <summary>
/// Called on the UI thread after backgroundWorker_DoWork() completes.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
contentPanel.Enabled = true;
this.UseWaitCursor = false;
}
当&#39;方法&#39;在backgroundWorker_DoWork(2-arg)
中执行,我将contentPanel
中的子控件的Enabled属性设置为true
。目的是在调用contentPanel
时启用backgroundWorker_RunWorkerCompleted()
时启用子控件。但是,在调用backgroundWorker_RunWorkerCompleted()
后,子控件仍然处于禁用状态。
据我所知,在禁用其父级(例如this question要求的内容)时,无法启用 的子控件,这是 not 我想做的事情。我希望在启用其父级(contentPanel
)时启用子控件(类似于在contentPanel
中启用backgroundWorker_RunWorkerCompleted()
时,在单击“提交”按钮之前启用的其他子控件的启用方式{1}})。
答案 0 :(得分:0)
Enabled
是环境属性。因此,如果您设置了子控件Enabled = false
,那么即使您设置了父控件Enabled = true
,如果在某个时刻显式设置了子控件,您仍然需要对子控件执行相同操作。
要在启用另一个控件时启用一个控件,请使用EnableChanged
事件。 E.g。
Control c1 = ...;
Control c2 = ...;
c1.EnabledChanged += delegate {
if (c1.Enabled)
c2.Enabled = true;
};
环境属性是一个控件属性,如果没有设置,则为 从父控件中检索。例如,一个Button就有了 默认情况下,BackColor与其父Form相同。欲获得更多信息 关于环境属性,请参阅AmbientProperties类或 控制类概述。 https://msdn.microsoft.com/en-us/library/system.windows.forms.control.font%28v=vs.110%29.aspx
答案 1 :(得分:0)
我发现btnSubmit_Click()
拨打的电话中隐藏了一些代码,导致childControl
停用。调用堆栈看起来像这样:
btnSubmit_Click()
combobox_SelectionChangeCommitted()
clearForm()
setEnabled()
setEnabled()
然后将childControl
的Enabled属性设置为combobox
的Enabled属性。由于contentPanel
已停用,combobox
也报告已停用(其Enabled
属性设置为true
,但检索Enabled
自contentPanel
被禁用后,属性值返回false,这会导致childControl.Enabled
被分配false
。
private void setEnabled(bool enabled)
{
...
combobox.Enabled = enabled;
childControl.Enabled = combobox.Enabled;
...
}
感谢@Loathing的专业知识。