List going back to 0 after new form - c#

I have this class:
public class Observador : iObservador
{
private List<Form> Forms = new List<Form>();
public void DeSubscribirse(Form form)
{
Forms.Remove(form);
}
public void Limpiar()
{
Forms.Clear();
}
public void Subscribirse(Form form)
{
Forms.Add(form);
}
public List<Form> DevolverSubscriptos()
{
return this.Forms;
}
}
Which is used on a base form I have like this:
public partial class FormBase : Form
{
public EE.Observador Watcher = new Observador();
public FormBase()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
this.Hide();
}
}
Which I use for the rest of my forms to be inherited from.
My idea is to have in all the forms a reference to the object Watcher from every place, with it having a reference for every form which is subscribed to it. So I can do for example, from FormB know that FormA is already subscribed with the method DevolverSubscriptos() (this means return subscribers) and access it to make it visible again after closing FormB.
The problem is that when I start FormB the list of Watcher with the whole forms is set back to 0.
What am I doing wrong? How can I solve it?
public partial class AdminUIGI : FormBase.FormBase
That's how I reference it.

Short answer: you're using an instance field. Each form is a separate instance, hence each has it's own copy of the EE.Observador.
So a quick and dirty fix would be to make this field static, i.e. shared by all instances of the given class. And if you want to improve, you might then consider reading about the Singleton pattern (mainly because you'll see it used a lot - but read on :) ), then read why using Singleton as a global variable is in fact an anti-pattern and move on to reading about dependency injection and IoC - which is how (in vacuum at least) your code should probably end up. (Note: for a quick and dirty solution static field is all you need).

#decPL I made it work with the singleton pattern doing this ` public sealed class Singleton
{
Singleton()
{
}
private static readonly object padlock = new object();
private static Singleton instance = null;
public static EE.Observador watcher = new Observador();
private Usuario userInstance = null;`

Related

use Winform Objects inside an Static Method

I have a problem that I could ignore a long time but now I have to solve it.
I have 3 GUI (Winform) 1 Main 1 Settings and 1 for a Webbrowser.
I need to call a Method that is in my Webbrowser Form inside my Main Form for that reason the Method is a static one.
But if I set it to static it giveĀ“s me an error if I try to work with the Objects from the Form.
public partial class Form3 : Form
{
public Form3()
{
InitializeComponent();
}
public static void WebLyrics(string url){
webBrowser1.Navigate(url);
}
}
The easiest way is to:
Add a static Instance property to the webbrowser form:
public partial class Form3 : Form
{
public Form3()
{
InitializeComponent();
Instance = this;
}
public static Form3 Instance { get; private set; }
public void WebLyrics(string url)
{
webBrowser1.Navigate(url);
}
}
and call the WebLyrics method via the Instance property in the other form:
public partian class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Navigate()
{
Form3.Instance.WebLyrics("www.stackoverflow.com");
}
}
I assumed you create both forms somewhere somehow...
You should consider changing the code. Why is your Form having a static method? It doesn't make any sense. The easiest way to achieve it is to pass reference to the Webbrowser Form into the Main Form. Or you can instantiate the Webbrowser form inside you Main Form and then show it.
But I suggest that you introduce a way of separating the UI from the business logic layer. Consider to introduce MVC / MVP pattern, to have a clear separation, and then the forms do not need to have references to each other directly.
The easiest (= least code) way to solve it is probably to use singletons for the forms as other have suggested, or even simpler to use the built in forms registry:
var myForm3 = Application.OpenForms.OfType<Form3>.FirstOrDefault();
I would probably prefer to use a separate singleton for holding the forms, as I would find it more maintainable. This would be a better separation of concerns in that the forms would not have to be created as singletons and could be reused in other ways. It is truly your app's UI layout that is the singleton.
Something like this:
public class AppLayout
{
public static AppLayout Instance {
get { ... }
}
public WebBrowserForm WebBrowser {get;private set;}
public MainForm Main {get;private set;}
public SettingsForm Settings {get;private set;}
}
Think of it like a typed variant of the Application singleton.

C# Component Container

I have a windows form and my own class in my project
I have a method in my own class
public object Sample(Form MyForm,string ComponentName)
{
}
I want to get components of the "MyForm" from another class How Can I Make THIs?
form class
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
}
MyOwnClass
public class Sample
{
public object GetComponentMethod(Form form,string ComponentName)
{
////
}
}
Have you tried with:
Control myControl= form.controls.Find(...)?
updated
Sorry but in this case I cannot understand what are you looking for!
updated
you have to create a public property Components! So you can retrieve data you need!
It looks like you are just trying to access members of one object from another object.
If so you need to expose some way of accessing a specific instance of a class.
If you will only ever have one instance (of say your Form1) the simplest way is to expose that single instance via a public static property. This is called a singleton pattern:
public partial class Form1 : Form
{
public static Form1 Singleton { get; private set; }
public Form1()
{
Form1.Singleton = this;
InitializeComponent();
}
}
You can the access your Form1 instance using Form1.Singleton.SomeProperty from anywhere.
I am not promoting any specific Singleton pattern here, as there are too many issues over thread safety, but for your simple example this will do the job. Call the static property "Singleton" or "This" or "SolutionToMyWoes" or whatever you like!

Is static function a right coding practice in this case, performance-wise and resource usage-wise?

There are many many similar links in stackoverflow, all which seem to be addressing complex functions (so quite difficult for me to understand what i really should go for). But mine is simple. I just want to know if declaring a function as static right way to go, if i can manage the same functionality even with a nonstatic approach? Which approach utilizes more memory?
Here's a sample code I've to implement, which is just showing up forms:
private void btn1_Click(object sender, EventArgs e)
{
Form1 frm = new Form1();
frm.ShowDialog();
}
Now I've to show this Form1 from many other forms in my program. So should it be better (right coding practice) to write the above piece of code where ever I want Form1 to be displayed, or should it be better to define it once as a static method in a static class, like this:
public static class globalvars
{
public static void Form1Show()
{
Form1 frm = new Form1();
frm.ShowDialog();
}
}
And then:
private void btn1_Click(object sender, EventArgs e)
{
globalvars.Form1Show();
}
I think if object of form is instantiated under the event where we want the form to be displayed (first non static approach), then the memory allocated for that process in the stack is destroyed right after its execution; while in the second static approach, the memory allocated stands throughout the lifetime of the application, and hence non-static approach is better right?
I know both works, and doesn't make a big difference, but still, which is the right coding practice, memory usage wise?
From a pure coding perspective any solution that avoid duplicating code is good. In your case you might want to add a static method to your Form1:
public Form1 : Form
{
public static void CreateNew()
{
using (var form = new Form1())
{
form.ShowDialog();
}
}
[...]
}
EDIT: From a memory point of view, the two samples you provided behave exactly the same. And modal dialogs should be disposed explicitly (with the using keyword for example).
Maybe I lost something there, but I didn't see any difference between them. The frm is a local variable, not a static field.
From a memory management standpoint since you're showing the same form in multiple places the optimal approach would be to implement the singleton pattern to ensure only one instance is used
All - I know this isn't exactly relevant as the question has been answered, but in order to answer nawfal's question regarding the singleton pattern I'm going to post a brief description and some code here.
#Nawfal - the singleton pattern is used to ensure that only a single instance of an object is ever used in an application. There are a huge number of different ways to achieve this, check out MSDN singleton pattern introduction for a basic introduction.
For non-trivial objects, e.g. classes this is the code I like to use:
1: Create a base Singleton class
public abstract class SingletonBase<T> where T : class
{
protected SingletonBase() { }
public static T Instance
{
get { return SingletonFactory.Instance; }
}
/// <summary>
/// The singleton class factory to create the singleton instance.
/// </summary>
class SingletonFactory
{
static SingletonFactory() { }
SingletonFactory() { }
internal static readonly T Instance = GetInstance();
static T GetInstance()
{
var theType = typeof(T);
T inst;
try
{
inst = (T)theType
.InvokeMember(theType.Name,
BindingFlags.CreateInstance | BindingFlags.Instance
| BindingFlags.NonPublic,
null, null, null,
CultureInfo.InvariantCulture);
}
catch (MissingMethodException ex)
{
throw new TypeLoadException(string.Format(
CultureInfo.CurrentCulture,
"The type '{0}' must have a private constructor to " +
"be used in the Singleton pattern.", theType.FullName)
, ex);
}
return inst;
}
}
2: Now inherit from your base class
public class myClass : SingletonBase<myClass>
{
// this is a private constructor
myClass() { }
private void somemethod()
{
}
public void SomeOtherMethod()
{
}
}
3: Finally anywhere you need to use myClass you call its instance as shown below
class Program
{
static void Main(string[] args)
{
// here you call the single instance of myClass
myClass myClassInstance = myClass.Instance;
// run the public someothermethod of myClass
myClassInstance.SomeOtherMethod();
}

Multiple .cs files and access to Form

I'm trying to write my first program in C# without the use of a tutorial. To ensure that I adopt from the start good coding practices, I want to create each class in an different .cs file. However, I'm running into some troubles when trying to access the elements of the program in such an .cs file.
For example, I have an Form1.cs with an Label and a Start button. When clicking on the start button, a text should appear in the Label. So:
In Form1.cs I have:
namespace TestProgram
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void startButton_Click(object sender, EventArgs e)
{
WriteToLabel message = new WriteToLabel();
message.WelcomeMessage();
}
}
}
And in my separate WriteToLabel.cs file:
namespace TestProgram
{
public class WriteToLabel
{
public void WelcomeMessage()
{
Form1 myForm = new Form1();
//myForm.. --> myForm doesn't have an 'outputLabel'?
outputLabel.Text = "Welcome!"; // This returns an error: 'The name outputLabel does not exits in the current context'.
}
}
}
'outputLabel' is the (Name) I've given the label, and this is in accordance to the name in Form1.Designer.cs.
Both files are using the same components such as 'using System';.
However, from my WriteToLabel.cs file I can't seem to access the Form which holds my program. I did manage to succeed to create different .cs files in an Console Application, which only added to my confusion. So, I have two questions:
First, how can I access the Form from a separate class (i.e. not an partial class) in a separate file?
Second, is this the good way to do it, or is it inefficient to create multiple instances of different classes?
Any thoughts or ideas are highly welcome,
Regards,
The designer automatically creates controls as private fields, because of that your WriteToLabel class can't access it. You need to change that.
Also a good start would be to change the class to something like that:
namespace TestProgram
{
public class WriteToLabel
{
Form1 form;
public WriteToLabel(Form1 form)
{
this.form = form;
}
public void WelcomeMessage()
{
//Form1 myForm = new Form1();
//myForm.. --> myForm doesn't have an 'outputLabel'?
form.outputLabel.Text = "Welcome!";
}
}
}
You're actually instantiating a new instance of Form1, whereas you need to pass in a reference to your existing instance:
public void WelcomeMessage(Form1 form)
{
form.outputLabel.Text = "Welcome";
}
You also need to ensure that outputLabel is a public (or internal) property/field of Form1 so you can set the value accordingly. Then the calling code is slightly different:
private void startButton_Click(object sender, EventArgs e)
{
WriteToLabel message = new WriteToLabel();
message.WelcomeMessage(this);
}
You need to make sure that Form1.outputLabel has public or internal visibility.
You only need something like a LabelWriter class if the class is going to share a significant amount of state or private methods. If all you have is a bunch of methods that set properties on separate objects, you might as well just keep it as a method on the same object (in this case the Form1 object):
void startButton_Click(object sender, EventArgs e)
{
displayWelcomeMessage();
}
void displayWelcomeMessage()
{
this.outputLabel = "Welcome!";
}

C# WinForms Passing Dictionary from Static Class To Non-Static Form Class

If I have a dictionary in a static class that gets updated randomly with data, how do I then pass this dictionary to the main form to display it in a grid view if the mainform is not static?
Surely if I create a new instance of the mainform I will have multiple mainforms everytime I try and do this (every 15 seconds) and I will lose data......right?
You should probably have a look at
C# - Singleton Pattern vs. Static
Classes
Implementing Singleton in C#
Implementing the Singleton Pattern
in C#
Leaving out the comments on your design (urgh... sorry couldn't help that) the cheap and easy thing is to give your static updater your main form and let the static class update your form manually.
public static class OmfgUpdater
{
private static MyForm _mainForm;
public static void RegisterForm(MyForm form)
{
_mainForm = form;
}
/*however this is done in your class*/
internal static void Update(Dictionary<string,string> updates)
{
_mainForm.Update(updates);
}
}
public class MyForm : Form
{
public MyForm()
{
OmfgUpdater.RegisterForm(this);
}
public void Update(Dictionary<string,string> updates)
{
/* oh look you got updates do something with them */
}
}
Disclaimer 1 : The statement in your question : "if I create a new instance of the mainform I will have multiple mainforms everytime I try and do this (every 15 seconds) and I will lose data......right?" is not at all clear to me. I'm going to answer here by interpreting your statement you want a static Dictionary as meaning you want one-and-only-one no matter how many other forms might be launched by one application instance.
Disclaimer 2 : Also the code I show here is meant to contrast with Will's answer where the static class updates the main form. And the answer here does not address dynamic linkage (databinding) at all : there's no code here for the user making a change on the form in the DataGridView, and having that back-propagate to update the underlying dictionary.
Assuming you want one-and-only-one Dictionary per application instance : If you have a public static class that holds a public static instance of a Dictionary like :
public static class DictionaryResource
{
// make dictonary internal so the only way to access it is through a public property
internal static Dictionary<string, int> theDictionary = new Dictionary<string, int>();
// utility methods :
// 1. add a new Key-Value Pair (KVP)
public static void AddKVP(string theString, int theInt)
{
if (! theDictionary.ContainsKey(theString))
{
theDictionary.Add(theString, theInt);
}
}
// 2. delete an existing KVP
public static void RemoveKVP(string theString)
{
if (theDictionary.ContainsKey(theString))
{
theDictionary.Remove(theString);
}
}
// 3. revise the value of an existing KVP
public static void ChangeDictValue(string theString, int theValue)
{
if(theDictionary.ContainsKey(theString))
{
theDictionary[theString] = theValue;
}
}
// expose the internal Dictionary via a public Property 'getter
public static Dictionary<string,int> TheDictionary
{
get { return theDictionary; }
}
}
At that point you can achieve dynamic updating of the contents of the Dictionary on a Form either through DataBinding techniques, or by defining custom events in the methods in the static class that are raised : these event are then subscribed to on the Form, and when you intercept these changes in the Form, you can then take action to update whatever representation you have on the Form.
Here's an example of defining a custom event in the static class :
// delegate signature
public delegate void addKVP(string sender, int value);
// delegate instance
public static event addKVP KeyValuePairAdded;
// delegate run-time dispatcher
public static void OnKVPAdded(string sender, int theInt)
{
if (KeyValuePairAdded != null)
{
KeyValuePairAdded(sender, theInt);
}
}
Then, as an example of how you subscribe to that custom event in a Form : in this case in the 'Load event :
DictionaryResource.KeyValuePairAdded += new DictionaryResource.addKVP(DictionaryResource_KeyValuePairAdded);
Where you have defined the handler for the event ... in the Form ... as :
private void DictionaryResource_KeyValuePairAdded(string theString, int theInt)
{
Console.WriteLine("dict update : " + theString + " : " + theInt);
}
A typical validation test executed in the Form's code might have calls like :
DictionaryResource.AddKVP("hello", 100);
DictionaryResource.AddKVP("goodbye", 200);
Obviously, you would modify that code in the Form's handler that justs prints a report to the console now to modify your DataGridView on the Form, or whatever other representation you are creating on the Form(s).

Categories

Resources