且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

子窗体从多个父窗体获取属性

更新时间:2023-12-06 09:45:04

使用接口,以定义将类(此处为表单)与另一个类相关联的合约.

An example using an Interface, to define a contract that relates a class (a Form, here) to another.

由于您有多个类(窗体)需要使用另一类(您的 Search 窗体)来使用通用属性和方法执行相同的任务,因此 worker 类( Search 表单)不需要知道实例化了哪个类,它只需要依赖Interface实现并使用通用的属性和方法来读取所需的值并写入其结果..

Since you have more than one class (Forms) that need use another class (your Search Form) to perform the same task using common properties and methods, the worker class (the Search Form) doesn't need to know which class instantiated it, it just need to rely on the Interface implementation and use the common properties and methods to read the values it needs and write its results.

创建一个接口,该接口定义创建 contract 的属性和方法(所有涉及的类都需要了解和依赖):

Create an Interface that defines the properties and methods that create the contract (what all the involved classes need to know and rely upon):

internal interface ISearch
{
    string Query { get; }
    int Other { get; }
    bool ReturnValue { get; set; }

    string GetSomeOtherValue();
}

所有要调用 Search 表单的表单都必须实现 ISearch 接口:

All the Forms that want to call the Search Form must implement the ISearch interface:

public class FrmMasterItem : Form, ISearch
{
    public FrmMasterItem() => InitializeComponent();

    // Interface implementation
    public string Query { get; private set; }
    public int Other { get ; private set; }
    public bool ReturnValue { get; set; }

    public string GetSomeOtherValue()
    {
        return "SomeValue";
    }

    private void button1_Click(object sender, EventArgs e)
    {
        this.Query = "SELECT someField FROM someTable";
        this.Other = 100;
        var search = new SearchForm();
        search.ShowDialog(this);
        if (this.ReturnValue)
            Console.WriteLine("All Good");
    }
}

在这里,在 Button.Click 事件上,设置了接口定义的属性,初始化并显示了 Search 表单,并设置了 Search 当前表单所有者:

Here, on a Button.Click event, the properties defined by the Interface are set, the Search Form is initialized and shown, setting the Search Form current Owner:

var search = new SearchForm();
search.ShowDialog(this);

关闭 Search 表单时,将由 Search 表单设置的值(此处为 ReturnValue 属性值将被读取以确定搜索结果.
当然,您可以返回任何其他内容或设置多个属性:例如,可以返回一个DataTable.

When the Search Form is closed, a value set by the Search Form (here, the ReturnValue propeprty value) is read to determine the result of the search.
Of course you could return anything alse or set more than one property: you could return a DataTable, for example.

搜索表单使用界面定义了当前的调用者表单:

The Search Form defines the current caller Form using the Interface:

ISearch myOwner = null;

然后验证当前所有者是否实现此接口:它必须知道它是否可以依赖 contract 定义的属性和方法.

Then verifies whether the current owner implements this interface: it must know if it can rely on properties and methods defined by the contract.

Type type = this.Owner.GetType();
if (typeof(ISearch).IsAssignableFrom(type)) {
    // (...)
    myOwner = (ISearch)this.Owner;
}

如果当前所有者未实现受信任的接口,则会引发异常: Search 表单无法读取和写入所需的值.
如果是这样,则会自行进行初始化,以从已知属性中读取值(当然,需要进行一些常规检查,即 null 或与类型相关的值).
关闭时,它将使用特定属性(此处为 ReturnValue )设置结果:

If the current owner doesn't implement the trusted Interface, then an exception is thrown: the Search Form cannot read and write the required values.
If it does, initializes inself reading the values from the known properties (some usual checks, i.e., null or type-related, are of course needed).
When closing, it sets the result using a specific property (ReturnValue, here):

myOwner.ReturnValue = true;
base.OnFormClosing(e);

搜索表单:

public partial class SearchForm : Form
{
    ISearch myOwner = null;
    string currentQuery = string.Empty;
    string otherValues = string.Empty;

    public SearchForm() => InitializeComponent();

    protected override void OnHandleCreated(EventArgs e)
    {
        base.OnHandleCreated(e);
        Type type = this.Owner.GetType();
        if (typeof(ISearch).IsAssignableFrom(type))
        {
            myOwner = (ISearch)this.Owner;
            this.currentQuery = myOwner.Query;
            this.otherValues = myOwner.GetSomeOtherValue();
            Console.WriteLine(this.currentQuery);
            Console.WriteLine(myOwner.Other);
            Console.WriteLine(this.otherValues);
        }
        else
        {
            throw new NotSupportedException("My Owner is not the right type!");
        }
    }
    protected override void OnFormClosing(FormClosingEventArgs e)
    {
        myOwner.ReturnValue = true;
        base.OnFormClosing(e);
    }
}