【问题标题】:Modify Windows Forms Control from another Project从另一个项目修改 Windows 窗体控件
【发布时间】:2013-05-10 02:44:12
【问题描述】:

我在用户控件MainScreen 中有一个控件lblDate。我想在Date 类中的一个方法中对其进行修改,该方法在另一个项目AoWLibrary 中。我无法引用它,因为 AoWLibrary 是第一个项目的依赖项。

我试图将 lblDate 设为静态,但编译器不断向我抛出错误,而且我有一个 Date 似乎无法访问的公共属性:

    public Label LabelDate
    {
        get { return lblDate; }
        set { lblDate = value; }
    }

在Date类中,我需要公共方法CalculateDate来修改lblDate的Text属性

    public static void CalculateDate()
    {
        GameDate = month.ToString() + "/" + displayDay.ToString() + "/" + year.ToString();

    // LabelDate.Text = GameDate;
    // This is essentially what I need to do
    }

此外,我什至无法在同一项目的其他控件中访问 lblDate。

【问题讨论】:

  • 如果你在控制器类中有一个实例化的对象,你可以从另一个类修改控件。
  • 设计师不是自动做的吗?
  • 你能在调用另一个表单的地方显示代码(或者代码示例就足够了)吗?
  • 我只使用一种形式。我只有几个用户控件。
  • 你是怎么调用你的CalculateDate方法的,它在你的主窗体中吗?

标签: c# winforms


【解决方案1】:

因此,总体思路是您需要跟踪范围内的内容。有很多方法可以去做你想做的事,但是它们中的任何一个都依赖于以你可能还不太完全理解的方式正确地相互引用的对象。不用担心——每个人都必须在某个时候解决这个问题。

当您尝试将该成员设为静态时编译器抱怨的原因是标签本身不是静态的。由于绑定到 MainScreen 的单个实例,它在静态上下文中没有任何意义,根据定义,静态上下文是一个范围,没有对特定 MainForm 的任何固有引用。

当然,您的 Date 类也是一个完全不同的上下文,但它的非静态成员确实可以访问 Date 的实例。在您创建它之前,这两个上下文之间没有任何路径。静态路由实际上会起作用(查找单例模式:想法是您静态存储类的第一个也是唯一一个实例并从其他地方引用它)但可能不是好的设计。其他方法是通过向 Date 传递 MainScreen 的实例(最好通过接口),甚至是 LabelDate 本身。所有这些都可以将您需要的两部分放在一起进行交谈。

但是,我建议您考虑一下您的游戏状态存储在哪里。它是在库中还是在消费程序集中?如果是前者,您可能需要考虑创建一个完整的无 GUI 模型,该模型需要在库类中存储和操作,并且只在主应用程序中使用现成的数据。另一种选择是您的模型位于主应用程序中,并在必要时回调您的库。在这种情况下,您现在可能应该坚持向库询问答案(或最多监听库中的事件),而不是期望它自己返回应用程序(无论是获取还是提供信息)。

在弄清楚如何做到这一点时,您可能会发现您的范围管理问题更容易处理。即使是一点点好的架构也能大有帮助。

但是,如果这一切有点压倒性,请不要过分强调它。听起来你这样做是为了好玩,这是一种很好的学习方式。你会遇到这样的问题,要么会遇到一个好的设计,要么会遇到一个不太好的设计,但无论哪种方式,你都在与重要的概念搏斗,并且会做得更好。

【讨论】:

  • 我刚刚签出 Singleton 并将其实现到我的代码中,我对它的工作方式非常满意。谢谢你的建议。应该对我有很大的帮助。
【解决方案2】:

属性 LabelDate 来自您的 userControl MainScreen 的类,但您没有实例化任何 userControl.. 那么您希望修改 MainScreen 的哪个实例?

你应该这样做

this.controlMainScreen.LabelDate = GameDate;

考虑到你在你的 cmets 中说,你有

 FormMain.Designer.cs there is: this.controlMainScreen = new Adventurers_of_Wintercrest.UserControls.MainScreen();

【讨论】:

  • 在 FormMain.Designer.cs 中有:this.controlMainScreen = new Adventurers_of_Wintercrest.UserControls.MainScreen();这不是应该发生的事情吗?
  • 查看我的编辑。当然,假设您的代码在 FormMain 中(您从不指定它的位置),这将起作用
  • 我发布的第一篇文章在 MainScreen.cs 中,它位于 Adventurers_of_Wintercrest.UserControls 命名空间中。第二位在 Date.cs 中,位于 AoWLibrary 命名空间中。
  • 属性 LabelDate 的代码应该在用户控件中(我猜是 MainScreen 名称),而不是在包含该控件的表单中(我猜是 FormMain 名称)。
【解决方案3】:

我宁愿建议你让你的 GameDate 方法返回一个字符串,然后从你的主项目中调用它,这本质上是库的用途。例如:

public static string CalculateDate()
{
    return month.ToString() + "/" + displayDay.ToString() + "/" + year.ToString();
}

//in your main project
LabelDate.Text = myLibrary.CalculateDate();

要从同一项目中的其他控件访问它,您应该使用委托 - 提供执行添加的委托,声明委托并从您的 CaculateDate 调用函数。示例:

public delegate void dateSet(string);

public void setDate(string date)
{
    labelDate.Text = date;
}

然后在您的CaculateDate 方法中:

labeldate.Invoke(new MainForm.dateSet(), GameDate);

【讨论】:

  • 代表应该去哪里?
  • 委托应该在标签所在的主项目中声明。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-25
  • 1970-01-01
相关资源
最近更新 更多