WinForms:响应正在应用的 BindingSource
WinForms: Respond to BindingSource being applied
当数据源应用到它的绑定控件时,是否有我可以锁定的事件得到通知?
或者是否有另一个事件,我可以保证数据源已被应用?
我正在使用 WinForms(来自 WPF)并使用带有数据绑定值的标签来确定我正在使用的控件类型。许多控件可能具有相同的标记值,我必须检索具有所需标记的控件才能执行业务逻辑。
问题是我不知道何时搜索标签值。我试图在调用后立即搜索标签值:
myBindingSource.DataSource = OutputFunctions.Instance;
//Yes... I'm binding to a singleton with a list of properties.
//Its not the best method, but works.
在我的 Form.Load
事件处理程序中。但是,在搜索过程中,我发现标签值没有设置。刚刚设置数据源怎么会这样?
从我的表单的内部管理代码隐藏可以看出,我已经通过设计器的 属性 window:
正确设置了值
this.textBoxDTemp.DataBindings.Add(new System.Windows.Forms.Binding(
"Tag",
this.myBindingSource,
"KNOB_DRIVER_TEMP",
true));
我查看了 BindingComplete
,老实说,它看起来很有前途,除了它不会在绑定初始化期间触发,即使该值据称是从数据传播的-源到目标控件。
编辑:
根据请求,数据源首先在表单的内部代码隐藏中设置如下:
this.myBindingSource.DataSource = typeof(OutputFunctions);
这里是单例,以防有帮助。
public class OutputFunctions
{
private static OutputFunctions instance;
public static OutputFunctions Instance
{
get
{
if (instance == null)
{
instance = new OutputFunctions();
}
return instance;
}
}
private OutputFunctions() { }
public string KNOB_DRIVER_TEMP { get { return "KNOB_DRIVER_TEMP"; } }
public string KNOB_PASSENGER_TEMP { get { return "KNOB_PASSENGER_TEMP"; } }
public string KNOB_FAN { get { return "KNOB_FAN"; } }
}
我认为您正在寻找控件的
"BindingContextChanged" 事件。
您是否试图在绑定发生时强制添加一些挂钩?。
由于您是在准备好整个表单并建立绑定之后进行查找,因此您可能可以挂接到 "LOAD" 事件。表单首先准备好所有内容,然后调用 "Load" 事件。如果有人订阅(收听)它,他们将收到通知。调用后,您可以 运行 并循环浏览表单上的所有控件并查找任何部分/组件/标记/控件类型等。
public Form1()
{
InitializeComponent();
this.VisibleChanged += Form1_VisibleChanged;
}
void Form1_VisibleChanged(object sender, EventArgs e)
{
if (!this.Visible)
return;
// Disable the event hook, we only need it once.
this.VisibleChanged -= Form1_VisibleChanged;
StringBuilder sb = new StringBuilder();
foreach (Control c in this.Controls)
sb.AppendLine(c.Name);
}
根据评论进行编辑。我从 LOAD 事件更改为 VISIBILITY 事件。在这一点上,表格现在正在显示,所以你所有的东西都应该完成并可用。因此,最初的检查是确保它变得可见。如果是这样,立即将其自身从事件处理程序中删除,您只需要完成一次,而不是每次都显示/隐藏/显示...
数据绑定应该在您的表单加载事件之前已经激活。您遇到的问题是因为由于数据绑定基础结构优化,不可见控件在第一次变得可见之前不会发生绑定。这可能是因为 WF 的设计者认为数据绑定将仅用于绑定数据属性(如 Text
等)并且对不可见控件执行此操作没有意义。
如果您不惧怕使用一些内部机制(或者 HighCore 用户会说 hack),那么以下助手将帮助您解决问题(我们已经使用类似的东西多年):
public static class ControlUtils
{
static readonly Action<Control, bool> CreateControlFunc = (Action<Control, bool>)Delegate.CreateDelegate(typeof(Action<Control, bool>),
typeof(Control).GetMethod("CreateControl", BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(bool) }, null));
public static void CreateControls(this Control target)
{
if (!target.Created)
CreateControlFunc(target, true);
else
for (int i = 0; i < target.Controls.Count; i++)
target.Controls[i].CreateControls();
}
}
并放在表单加载事件处理程序的开头
this.CreateControls();
当数据源应用到它的绑定控件时,是否有我可以锁定的事件得到通知?
或者是否有另一个事件,我可以保证数据源已被应用?
我正在使用 WinForms(来自 WPF)并使用带有数据绑定值的标签来确定我正在使用的控件类型。许多控件可能具有相同的标记值,我必须检索具有所需标记的控件才能执行业务逻辑。
问题是我不知道何时搜索标签值。我试图在调用后立即搜索标签值:
myBindingSource.DataSource = OutputFunctions.Instance;
//Yes... I'm binding to a singleton with a list of properties.
//Its not the best method, but works.
在我的 Form.Load
事件处理程序中。但是,在搜索过程中,我发现标签值没有设置。刚刚设置数据源怎么会这样?
从我的表单的内部管理代码隐藏可以看出,我已经通过设计器的 属性 window:
正确设置了值this.textBoxDTemp.DataBindings.Add(new System.Windows.Forms.Binding(
"Tag",
this.myBindingSource,
"KNOB_DRIVER_TEMP",
true));
我查看了 BindingComplete
,老实说,它看起来很有前途,除了它不会在绑定初始化期间触发,即使该值据称是从数据传播的-源到目标控件。
编辑: 根据请求,数据源首先在表单的内部代码隐藏中设置如下:
this.myBindingSource.DataSource = typeof(OutputFunctions);
这里是单例,以防有帮助。
public class OutputFunctions
{
private static OutputFunctions instance;
public static OutputFunctions Instance
{
get
{
if (instance == null)
{
instance = new OutputFunctions();
}
return instance;
}
}
private OutputFunctions() { }
public string KNOB_DRIVER_TEMP { get { return "KNOB_DRIVER_TEMP"; } }
public string KNOB_PASSENGER_TEMP { get { return "KNOB_PASSENGER_TEMP"; } }
public string KNOB_FAN { get { return "KNOB_FAN"; } }
}
我认为您正在寻找控件的
"BindingContextChanged" 事件。
您是否试图在绑定发生时强制添加一些挂钩?。
由于您是在准备好整个表单并建立绑定之后进行查找,因此您可能可以挂接到 "LOAD" 事件。表单首先准备好所有内容,然后调用 "Load" 事件。如果有人订阅(收听)它,他们将收到通知。调用后,您可以 运行 并循环浏览表单上的所有控件并查找任何部分/组件/标记/控件类型等。
public Form1()
{
InitializeComponent();
this.VisibleChanged += Form1_VisibleChanged;
}
void Form1_VisibleChanged(object sender, EventArgs e)
{
if (!this.Visible)
return;
// Disable the event hook, we only need it once.
this.VisibleChanged -= Form1_VisibleChanged;
StringBuilder sb = new StringBuilder();
foreach (Control c in this.Controls)
sb.AppendLine(c.Name);
}
根据评论进行编辑。我从 LOAD 事件更改为 VISIBILITY 事件。在这一点上,表格现在正在显示,所以你所有的东西都应该完成并可用。因此,最初的检查是确保它变得可见。如果是这样,立即将其自身从事件处理程序中删除,您只需要完成一次,而不是每次都显示/隐藏/显示...
数据绑定应该在您的表单加载事件之前已经激活。您遇到的问题是因为由于数据绑定基础结构优化,不可见控件在第一次变得可见之前不会发生绑定。这可能是因为 WF 的设计者认为数据绑定将仅用于绑定数据属性(如 Text
等)并且对不可见控件执行此操作没有意义。
如果您不惧怕使用一些内部机制(或者 HighCore 用户会说 hack),那么以下助手将帮助您解决问题(我们已经使用类似的东西多年):
public static class ControlUtils
{
static readonly Action<Control, bool> CreateControlFunc = (Action<Control, bool>)Delegate.CreateDelegate(typeof(Action<Control, bool>),
typeof(Control).GetMethod("CreateControl", BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { typeof(bool) }, null));
public static void CreateControls(this Control target)
{
if (!target.Created)
CreateControlFunc(target, true);
else
for (int i = 0; i < target.Controls.Count; i++)
target.Controls[i].CreateControls();
}
}
并放在表单加载事件处理程序的开头
this.CreateControls();