1

I would like to know the correct way(best looking) to set, for example, a label from a class other than my MainWindow.

At the moment, I would do something like this:

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

But I feel like this is kind of bad practice.
It feels really bad when you have more than 20 classes and all have a field or property of parent.
How would you solve a problem like this?

Ken Kin
  • 4,503
  • 3
  • 38
  • 76
Nick3
  • 639
  • 1
  • 14
  • 40
  • I think you mean `a.WriteToLabel();` – I4V Jan 12 '13 at 21:49
  • yeah, that's a typo... Edited. Thanks!! – Nick3 Jan 12 '13 at 21:51
  • The question is why you need to set a `Label's` Text from a class that doesn't belong to the `MainWIndow`. The form of your label is the controller of it's Gui, the classes just have to _provide_ what you want to show in the form. – Tim Schmelter Jan 12 '13 at 21:52
  • It's just an example, the function could fill a list in the MainWindow, or maybe set a textbox or multiple other controls. It's not really about the label... – Nick3 Jan 12 '13 at 22:09

5 Answers5

3

Why not passing label1 as a parameter?

With:

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

You would use:

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

It's conventionally better to avoid coupling in your code as much as possible. I wouldn't add a reference to a window. I'd rather parametrize my methods as much as I can.

e_ne
  • 8,340
  • 32
  • 43
  • Exaktly, I would really like to avoid the coupling, but as I said in an other comment, I don't know what to do, for exaple if a Thread wants to write to the GUI, or maybe something like if a file is read, then something in the GUI should update. Then this would not work. How can I do it den? – Nick3 Jan 12 '13 at 23:27
  • 1
    @Nick3 Coupling is almost always necessary at least once (otherwise your modules would be useless), it should just be avoided as much as possible. If you need to operate on a window from a different thread, you can pass it through a `ParametrizedThreadStart` delegate, or you can use the static `Application.Current.MainWindow` if you really need a reference to it. Furthermore, with .NET 4.5 there's so much you can do with the `async/await` keywords that would simplify your code while offering asynchronous execution. – e_ne Jan 12 '13 at 23:36
2

I think your practice is overall good. But I would also "keep track" of the children I've instanciated through a List so I could also, eventually, search for a specific one using Linq extensions. I also corrected some minor errors in your code (naming convention for the parent member of MyClass and the void result of WriteToLabel() being assigned to MyClass instance in the parent constructor.

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";
    } 
}
Tommaso Belluzzo
  • 23,232
  • 8
  • 74
  • 98
0

use 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;
    } 
}
burning_LEGION
  • 13,246
  • 8
  • 40
  • 52
0

The question is why you need to set a Label's Text from a class that doesn't belong to the MainWindow. The form of your label is the controller of it's GUI, the classes just have to provide what you want to show in the form.

So this is better practise.

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";
    } 
}
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • As I commeted on an other answer, it may not be the best example, but maybe I start a Thread in the class and I want to set the text when something occures. In the example this would work, but I want something general for all times I would like to change something in my GUI – Nick3 Jan 12 '13 at 22:12
0

As your class are fully aware of each other, a good way is to provide Property accessor.

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";
    } 
}
Tilak
  • 30,108
  • 19
  • 83
  • 131