WinForms:响应正在应用的BindingSource

时间:2015-10-23 16:23:01

标签: c# winforms events data-binding binding

当数据源应用于绑定控件时,是否存在可以锁定以通知的事件?

还是有另一个事件,我保证已经应用了数据源?

<小时/> 我正在使用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事件处理程序中。但是,在搜索过程中,我看到标签值未设置。如果我只是设置数据源,那该怎么办?

从我的表单的内部托管代码隐藏中可以看出,我已经通过设计器的Property窗口正确设置了值:

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"; } }
}

2 个答案:

答案 0 :(得分:3)

应该在表单加载事件之前激活数据绑定。您遇到的问题是,由于数据绑定基础结构优化,对于不可见控件的绑定不会发生,直到它们第一次可见。这可能是因为WF的设计者认为数据绑定将仅用于绑定数据属性(如Text等),并且对于不可见的控件来说这样做是没有意义的。

如果您不害怕使用某些内部(或者用户HighCore会说黑客),那么以下帮助将有助于解决您的问题(我们使用类似的东西多年):

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();

答案 1 :(得分:1)

我认为您正在寻找控件的

&#34; BindingContextChanged&#34;事件

你是否试图在绑定发生时强制添加一些钩子?

因为你正在寻找整个表格准备好并建立绑定后,你可能会挂钩&#34; LOAD&#34;事件。表单首先准备好所有内容,然后调用&#34; Load&#34;事件。如果订阅(收听)任何内容,将通知他们。一旦调用它,您就可以运行并循环遍历表单上的所有控件,并查找任何部件/组件/标签/控件类型等。

    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事件。此时,表单现在正在显示,因此您的所有内容应该完成并可用。因此,初步检查是为了确保它变得可见。如果是这样,立即从事件处理程序中删除它,你只需要它完成一次而不是每次可能显示/隐藏/显示...