【问题标题】:Child Form getting properties from multiple parent Forms子表单从多个父表单获取属性
【发布时间】:2019-05-16 07:23:49
【问题描述】:

我能否从两个父级(FrmMasterItemFrmMasterPackage)获取一个包含 DataGridView 的表单 (FrmItemSearch) 的查询值并将所选值传递给其父级表单?

我已经尝试过让FrmItemSearchFrmMasterItem 获取一些数据,它可以显示数据,但我希望FrmItemSearch 也从FrmMasterPackage 获取数据,所以我只需要一个带有DataGridView 执行所有的搜索操作。

//this is my MasterItem Form
public partial class FrmMasterItem : Form
{
      public string myQuery { get; set; }
      public FrmMasterItem() { InitializeComponent(); }

      public void SearchItemCode_Click(object sender, EventArgs e)
      {
            this.myQuery = "select * from InItemMst";

            FrmItemSearch fcd = new FrmItemSearch(this);
            fcd.ShowDialog();
      }
}


//this is my MasterPackage Form
public partial class FrmMasterPackage : Form 
{
    public string sQuery { get; set; }
    public FrmMasterPackage() { InitializeComponent(); }

    public void SearchItemCode_Click(object sender, EventArgs e)
    {
          this.sQuery = "select * from InPackagehdr";
          //I want to get this query on FrmSearchItem
    }
}  

//this is my Item Search Form
public partial class FrmItemSearch : Form
{
      private FrmMasterItem f_mb;
      public FrmItemSearch(FrmMasterItem fmb)
      {
            f_mb = fmb;
            InitializeComponent();
      }

      private void FrmItemSearch_Load(object sender, EventArgs e)
      {
            MySqlConnection conn = DBUtils.GetDbConnection();
            conn.Open();

            string query = this.f_mb.myQuery;//this is only MasterItem Data i want to make some selection for MasterPackage here so the Gridview can View MasterPackage data using sQuery Value from FrmMasterPackage

            MySqlDataAdapter adapter = new MySqlDataAdapter(query, conn);
            DataTable dt = new DataTable();
            adapter.Fill(dt);
            BindingSource bSource = new BindingSource();
            bSource.DataSource = dt;
            dataGridView1.DataSource = bSource;
      }
}

【问题讨论】:

  • f_mbnot a nice 名称。
  • 我不知道我应该使用什么名称,只是测试一些代码 :) 顺便说一句,我是 C# 中的新手
  • 您可以在子(search 表单)构造函数中传递当前调用者(master 表单之一)查询字符串。给予或接受你现在正在做的事情,只需传递一个字符串而不是表单。或者让你的Form对象实现一个contract resolver接口,暴露一个know属性:设置为查询字符串的属性,所以你不需要知道是什么Form打开了Search,你只需要知道它必须实现该接口,从而公开该属性。有问题的表单可以是 Seach 所有者。 (您创建一个使用var someForm = new SomeForm(this) 指定所有者的表单)
  • 感谢您的建议,但我需要从每个主表单中获取超过 1 个值,所以我只想知道是否有可能在我的搜索表单中获取 2 个主表单
  • 定义一个具有多个属性的接口 :) 或返回复杂对象(类、JSON 等)的属性/方法。

标签: c# winforms


【解决方案1】:

一个使用Interface 的示例,用于定义将一个类(此处为表单)与另一个类关联的合同

由于您有多个类(表单)需要使用另一个类(您的 Search 表单)来使用通用属性和方法执行相同的任务,因此 worker 类(@987654324 @Form) 不需要知道是哪个类实例化了它,只需要依赖接口实现,使用常用的属性和方法,读取它需要的值,写入它的结果。

创建一个接口,定义创建契约的属性和方法(所有涉及的类都需要知道和依赖):

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

    string GetSomeOtherValue();
}

所有想调用SearchForm的Form都必须实现ISearch接口:

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表单设置为当前Owner

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

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

搜索表单使用接口定义当前调用者表单:

ISearch myOwner = null;

然后验证当前所有者是否实现了这个接口:它必须知道它是否可以依赖合约定义的属性和方法。

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

如果当前所有者没有实现可信接口,则抛出异常:Search 表单无法读取和写入所需的值。
如果是,则初始化自身,从已知属性中读取值(当然需要一些常用检查,即null 或类型相关)。
关闭时,它使用特定属性设置结果(ReturnValue,此处):

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

Search 表单:

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

【讨论】:

  • 你能告诉我如何获取 datagridview 值,因为我的搜索表单使用的是 datagridview,我想将 datagridview 中的选定值传递回我的所有者表单上的文本框,如果我也问的话,对不起很多.. @Jimi
  • 这取决于你想返回什么。在示例中,ReturnValuebool,但您可以根据需要定义它。也许,将其设置为返回一个字符串。例如,您可以为其分配[DataGridView].CurrentCell.Value.ToString()。当 Search 表单关闭时,打开它的表单将在 ReturnValue 中具有选定的值,您可以将其分配给 TextBox(或任何其他接受字符串的内容)。
  • 我想从我的主表单文本框的搜索表单中返回选定的 id 值,如果我双击 datagridview 上的行标题,那么 datagridview 将关闭并将选定的 id 值传递给我的 masterForm IdTextBox
  • 好吧,然后订阅RowHeaderMouseDoubleClick 并将所选行的正确单元格值分配给ReturnValue[DataGridView].Rows[e.RowIndex].Cells[X].Value.ToString() 其中X 是包含的列的索引或名称您要返回的值。
  • f_mb.txtItemId.Text = dataGridView1.CurrentRow.Cells[0].Value.ToString(); 我是这样做的,但它说“对象引用未设置为对象的实例。”
【解决方案2】:

只需在主表单中声明您的 myQuery 变量,如下所示

public static string myQuery

然后你可以使用master的对象访问这个变量到任何形式

【讨论】:

  • myQuery 对 FrmItemSearch 很好,我想做的是让我在 FrmMasterPackage 上的 sQuery 也可以在 FrmItemSearch 上使用
  • static 意味着一个类只存在一个给定变量的实例。静态变量用于定义常量,因为它们的值可以通过调用类来检索,而无需创建它的实例。静态变量可以在成员函数或类定义之外初始化
【解决方案3】:

我还可以补充一点,将 DAL(数据访问层)或 BLL(业务逻辑层)代码添加到您的表单被认为是不好的做法?我建议为此类代码创建目录和类。

我建议如下:

public partial class FrmItemSearch : Form
{
      private FrmMasterItem f_mb;
      public FrmItemSearch(FrmMasterItem fmb)
      {
            f_mb = fmb;
            InitializeComponent();
      }

      private void FrmItemSearch_Load(object sender, EventArgs e)
      {
            ataGridView1.DataSource = DAL.GetSourceFromDatabase(DAL.query);
      }
}

public static class DAL
{
    public static string query = "MyQuery"

    public static BindingSource GetSourceFromDatabase(string query)
    {
        MySqlConnection conn = DBUtils.GetDbConnection();
        conn.Open();
        MySqlDataAdapter adapter = new MySqlDataAdapter(query, conn);
        DataTable dt = new DataTable();
        adapter.Fill(dt);
        BindingSource bSource = new BindingSource();
        bSource.DataSource = dt;
        return dt;
    }
}

【讨论】:

    猜你喜欢
    • 2012-11-12
    • 2022-01-16
    • 1970-01-01
    • 1970-01-01
    • 2016-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多