C# WinForms 'this.Controls.Find' in a separate class - c#

I am trying to divide my program into classes to reduce clutter and increase readability.
In one of my methods, I need to find the location of a label on the screen.
this.Controls.Find worked before I moved everything into separate classes but it doesn't exist anymore because I am no longer executing it in the same class as the controls. I tried Main.Controls.Find (Main.cs is where my form is executed and set out) but this also didn't work and I got the error, "An object reference is required for the non-static field, method, or property 'Control.Controls'"
How do I reference the controls? Do I need to add an additional using statement?
Thanks,
Josh

You need a reference to the form, passed down to the newly introduced method (or class).
Before
public class Main : Form {
public void Whatever() {
...
this.Controls.Find(...);
}
}
After
public class Main : Form {
public void Whatever() {
...
new Helpers().HelperMethod( this );
}
}
public class Helpers {
public void HelperMethod( Form form ) {
...
form.Controls.Find
}
}
or
public class Main : Form {
public void Whatever() {
...
new Helpers( this ).HelperMethod();
}
}
public class Helpers {
private Form Form { get; set; }
public Helpers( Form form ) {
this.Form = form;
}
public void HelperMethod() {
...
this.Form.Controls.Find
}
}

Related

Parameters in constructor in Avalonia Window

Let's take simple window:
public partial class NewWindow : Window
{
public NewWindow(CustomType variableName)
{
InitializeComponent();
//do stuff with your variable
#if DEBUG
this.AttachDevTools();
#endif
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
}
When you do thing like this, application will no longer compile:
Unable to find public constructor for type Project:Project.Views.NewWindow() Line 1, position 2
Is there a way to bypass it? It forces me to use some ancient methods like controlling things via public static variables, which in normal scenario can be avoided by using constructors.
You might have already found this out, but the XAML template requires a public paramterless constructor. However, that doesn't mean you can't add your own second constructor.
public partial class NewWindow : Window
{
public NewWindow()
{
InitializeComponent();
}
public NewWindow(CustomType variableName)
: this()
{
//do stuff with your variable
#if DEBUG
this.AttachDevTools();
#endif
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
}

Accessing parent instance data from child instances in .NET 5.0 / C# 9.0

I have a .NET 5.0 web application that instantiates classes for each of the endpoints. Those classes instantiate child classes. Is there a more elegant or efficient way to access parent instance data from child instances besides the way I'm doing it right now?
As an example:
public class ComponentClass
{
private PageClass _page;
public ComponentClass(PageClass page)
{
_page = page;
}
public void ComponentMethod()
{
// Call the method from the parent instance
page.PageMethod();
}
}
public class PageClass
{
private ComponentClass _component;
public PageClass()
{
_component = new ComponentClass(this);
}
public async Task ProcessRequest(HttpContext context)
{
// Call the component's method
_component.ComponentMethod();
}
public void PageMethod()
{
// Do something here
}
}
Specifically, I'm trying to avoid having to pass this to every ComponentClass instance...
If you want to call a method on the parent, then you have two options. The first is to pass a reference of the parent into the child. There's no way around this, an object has no way to know in which object it is referenced from. In fact, it could be referenced by multiple parent objects.
The better solution is to use events. That way the child never knows anything about the parent(s) and can emit events that any number of components can subscribe to. See here for more details on events. For example, your component could look something like this:
public class Component
{
public event EventHandler Tick;
public void DoSomething()
{
EventHandler handler = Tick;
handler?.Invoke(this, new EventArgs());
}
}
And your PageClass:
public class PageClass
{
public Component _component { get; set; }
public void Init()
{
_component = new Component();
_component.Tick += Component_Tick;
}
public void MakeComponentTick()
{
// This method is just for testing, it's likely this would be triggered by user input
_component.DoSomething();
}
private void Component_Tick(object sender, EventArgs e)
{
Console.WriteLine("Component ticked!");
}
}

call the function in another class(c#)

I am trying to migrate one of my macOS app to Windows UWP.
There is a requirement that I need to call the function in another class
namespace MyApp
{
public sealed partial class MainPage : Page
{
public bool isOk;
public MainPage()
{
}
public void doSomething(){
};
/*
public static void doSomething(){
isOk=false;// isOk is inaccessible
};*/
}
public sealed partial class AnotherPage : Page
{
public AnotherPage()
{
//call doSomething() in MainPage
}
}
}
it is very easy to implement this in objective-c via protocol(interface)
but in c#, the mechanism of the interface is different from the objective-c protocol.
of course, I can use the code below
MainPage mainPage=new MainPage();
mainPage.dosomthing();
but I wonder if this is valid for Page object related to the XAML file.
or there is a common usage to call the function in another class?
Your comment welcome
NOTE: This is an answer to your question but from a design perspective this is bad.
You need a reference to the instantiated MainPage. I'm sure there's one in the framework but for example just so this can be understood let's make a public static class to hold this reference.
public static class Global
{
public static Page MainPage { get; set; }
}
Now in the MainPage constructor assign itself to this property of the static Global class.
public MainPage()
{
Global.MainPage = this;
}
Now from any other page you can access it.
public AnotherPage()
{
Global.MainPage.doSomething();
}

How to include the methods from on class in another

I want to me able to include a bunch of methods from one main class into several Forms.
Example
class Master{
public void kill(){
this.Hide()
}
}
class b : Form{
//What must I do so that class 'b' can call kill, an it would mean that b would close
}
First i thought if Master inherits Form, then b can inherit Master, but that failed. Not a clue, really struggling, all comments welcome. Thank you!
Edit
Ok, there are lots of functions and variables which need to be copied into the form. This is why i wanted something similar to sub classing.
Make kill into an extension method.
public static class FormExtensions
{
public static void Kill(this Form form)
{
...
}
}
Or if you don't want it to apply to every form, then you can extend a marker interface and apply it to the applicable forms
public interface IKillable
{ }
public static class KillableExtensions
{
public static void Kill(this IKillable form)
{
...
}
}
make a master and call it
class b : Form{
//What must i do so that class be can call kill
Master _master = new Master();
void Stuff()
{
_master.kill();
}
}
You can also make extension methods.... assuming there is no members of Master that you want to access
Or you could make Master inherit Form, then make b inherit Master
You can call a method from other class by creating its object.
EXAMPLE:
public class A
{
public void myMethod()
{
}
}
public class B
{
A a = new A(); // here 'a' is an object of class 'A'
a.myMethod();
}

Trying to call methods between classes created dynamically

I have been trying to work out how to call a method in a different class. Both classes are created dynamically at run-time. Most of the issues I have seen here relate to inheritance, which is different from what I have (I think.)
I am still fairly new to C#, and am trying to test some concepts out.
The first class is something like this:
public class Record
{
CustomPanel _panel;
public void recordFunc(){}
}
The internally created class has something like this:
public class CustomPanel : Panel
{
List<Control> _myControls = new List<Control>;
// _myControls[0] += new EventHandler(myFunc);
public void myFunc(object sender, EventArgs e)
{
// parentClass.recordFunc();
}
}
My objective is to create a Record at run-time from a database call. At that point, it creates a Panel (from my CustomPanel class) that gets added to a FlowLayoutControl. When events are fired from the panel's internal controls, I need to have it update parts of the parent Record class.
Any help is greatly appreciated.
I'm not 100% sure what you're asking, but it seems you want to know how to call a function on a class, when you don't know the class type at runtime, but it could be one or many record types. Is that correct?
If so, a way to cleanly achieve the above is to implement an interface on your derived types and call the interface method. For instance, if you have multiple "Record" classes and don't know the type at runtime, try the following:
public interface IRecord
{
void RecordFunc();
}
public class ARecord : IRecord
{
public void RecordFunc()
{
Console.WriteLine("ARecord.RecordFunc");
}
}
public class AnotherRecord : IRecord
{
public void RecordFunc()
{
Console.WriteLine("AnotherRecord.RecordFunc");
}
}
public class CustomPanel : Panel
{
private IRecord _parentRecord;
// Where parentRecord could be ARecord or AnotherRecord
public class CustomPanel(IRecord parentRecord)
{
_parentRecord = parentRecord;
}
public void MyFunc(object sender, EventArgs e)
{
_parentRecord.RecordFunc();
}
}
If that's not what you're looking for, please clarify.
There is no magic instance of the Record class available from within a CustomPanel just because a Record instance contains a CustomPanel. You'll have to set up such a relationship yourself. E.g.
public class Record
{
CustomPanel _panel;
public CustomPanel panel
{
get { return _panel; }
set { _panel = value; _panel.parent = this; }
}
public void recordFunc(){}
}
public class CustomPanel : Panel
{
public Record parent { get; set; }
public void myFunc(object sender, EventArgs e)
{
parent.recordFunc();
}
}

Categories

Resources