【问题标题】:The "Correct" way to set control value from other class从其他类设置控制值的“正确”方式
【发布时间】:2013-01-12 21:46:31
【问题描述】:

我想知道正确的方法(最好看)来设置,例如,来自我的MainWindow 以外的类别的标签。

目前,我会做这样的事情:

public partial class MainWindow: Window {
    public MainWindow() {
        InitializeComponent();

        MyClass a=new MyClass(this);
        a.WriteToLabel();
    }
}

class MyClass {
    MainWindow parent;

    public MyClass(MainWindow parent) {
        this.parent=parent;
    }

    public void WriteToLabel() {
        parent.label1.Text="Test";
    }
}

但我觉得这是一种不好的做法。
当你有超过 20 个类并且都有一个 parent 的字段或属性时,感觉真的很糟糕。
你会如何解决这样的问题?

【问题讨论】:

  • 我想你的意思是a.WriteToLabel();
  • 是的,这是一个错字...已编辑。谢谢!!
  • 问题是为什么需要从不属于MainWIndow 的类中设置Label's 文本。标签的形式是它的 Gui 的控制器,类只需要提供你想在表单中显示的内容。
  • 这只是一个例子,该函数可以在主窗口中填充一个列表,也可以设置一个文本框或多个其他控件。这与标签无关......

标签: c#


【解决方案1】:

为什么不将label1 作为参数传递?

与:

class MyClass
{
    public void WriteToLabel(Label label)
    {
        label.Content = "Test";
    }
}

你会使用:

var a = new MyClass();
a.WriteToLabel(label1);

按照惯例,最好尽量避免代码中的耦合。我不会添加对窗口的引用。我宁愿尽可能地参数化我的方法。

【讨论】:

  • 没错,我真的很想避免耦合,但正如我在另一条评论中所说,我不知道该怎么做,例如,如果线程想要写入 GUI,或者可能类似于如果读取文件,则 GUI 中的某些内容应该更新。那么这是行不通的。我该怎么做呢?
  • @Nick3 耦合几乎总是至少需要一次(否则您的模块将毫无用处),应尽可能避免。如果您需要从不同的线程对窗口进行操作,可以通过ParametrizedThreadStart 委托传递它,或者如果您确实需要对它的引用,可以使用静态Application.Current.MainWindow。此外,在 .NET 4.5 中,您可以使用 async/await 关键字做很多事情,这些关键字可以在提供异步执行的同时简化您的代码。
【解决方案2】:

我认为你的练习总体上很好。但我也会“跟踪”我通过列表实例化的孩子,因此我最终也可以使用 Linq 扩展搜索特定的孩子。 我还更正了代码中的一些小错误(MyClass 的父成员的命名约定以及在父构造函数中将 WriteToLabel() 分配给 MyClass 实例的 void 结果。

public partial class MainWindow : Window
{
    private List<MyClass> children;

    public MainWindow()
    {
        children = new List<MyClass>();

        InitializeComponent();

        MyClass child = InstantiateChild();
        child.WriteToLabel();
    }

    private MyClass InstantiateChild()
    {
        MyClass child = new MyClass(this);
        children.Add(child);

        return child;
    }
}

public class MyClass
{
    private MainWindow m_Parent;

    public MyClass(MainWindow parent)
    {
        m_Parent = parent;
    }

    public void WriteToLabel()
    {
        m_Parent.label1.Text = "Test";
    } 
}

【讨论】:

    【解决方案3】:

    使用Fluent interface

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            MyClass a = new MyClass(this).WriteToLabel("Test");
        }
    }
    
    class MyClass
    {
        MainWindow parent;
    
        public MyClass(MainWindow parent)
        {
            this.parent = parent;
        }
    
        public MyClass WriteToLabel(string txt)
        {
            parent.label1.Text = txt;
            return this;
        } 
    }
    

    【讨论】:

      【解决方案4】:

      问题是为什么您需要从不属于MainWindow 的类中设置LabelText。标签的形式是它的 GUI 的控制器,类只需要提供你想在表格中显示的内容。

      所以这是更好的练习。

      public partial class MainWindow : Window
      {
          public MainWindow()
          {
              InitializeComponent();
              MyClass a = new MyClass();
              string data = a.GetData();
              label1.Text = text;
          }
      }
      
      class MyClass
      {
          public MyClass()
          {
              this.parent = parent;
          }
      
          public stringGetData()
          {
              return "Test";
          } 
      }
      

      【讨论】:

      • 正如我对另一个答案的评论,它可能不是最好的例子,但也许我在课堂上启动了一个线程,并且我想在发生某些事情时设置文本。在示例中这会起作用,但我想要一些通用的东西我想在我的 GUI 中更改一些东西
      【解决方案5】:

      由于您的班级彼此完全了解,因此提供属性访问器是一个好方法。

      public partial class MainWindow : Window
      {
          public MainWindow()
          {
              InitializeComponent();
              MyClass a = new MyClass(this);
              a.WriteToLabel();
          }
      
      
          public string LabelText
          {  
              get { return label1.Text; }
              set {
                      if (this.InvokeRequired) 
                      {
                         this.BeginInvoke(
                             delegate() => 
                                      { 
                                        label1.Text =value;
                                      })};
                       }
                       else
                       {
                          label1.Text = value;
                       }
                    }
      
      }
      
      class MyClass
      {
          MainWindow parent;
      
          public MyClass(MainWindow parent)
          {
              this.parent = parent;
          }
          public void WriteToLabel()
          {
              parent.LabelText = "Test";
          } 
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-08-15
        相关资源
        最近更新 更多