I'm making c# app where I need to access method in partial class from another class.
To be more specific I want to add items to listview from class that is different from partial class but in same namespace.
I tried like this:
public partial class Aa : Form
{
public static void UpdateListView(string[] array)
{
if (ProcessNetUsageList.InvokeRequired)
{
ProcessNetUsageList.Invoke(new Action<string[]>(UpdateListView), array);
}
else
{
ListViewItem item = new ListViewItem(array[0]);
for (int i = 1; i < 4; i++)
item.SubItems.Add(array[i]);
ProcessNetUsageList.Items.Add(item);
}
}
}
and then access it from another class like:
class Test
{
test()
{
ProgramName.Aa.UpdateListView(someArray);
}
}
But its giving an error because static method can only access static variables,and my listview isnt static(i created that listview in vs designer).
If i remove static keyword from method in partial class then i cant access it.I tried to create instance of partial class but without success.Any idea is welcome
note:Im using Invoke in my UpdateListView method because later that will be running on new thread
The nature of an object-oriented language is that objects don't have universal access to modify other objects. This is a good thing.
You've provided relatively little code so it's hard to provide a perfect answer here, but there are a few paradigms that resolve this issue.
One is to pass the instance to your test class, like this:
class Test
{
test(ProgramName.Aa form)
{
form.UpdateListView(someArray);
}
}
Or, if class test actually contains the ListView, you can pass that to a static method in Aa.
class Test
{
ListView someListView;
test()
{
ProgramName.Aa.UpdateListView(someListView, someArray);
}
}
Ultimately, you should think about the logical relationship between these objects to determine how these objects should communicate.
Remove the static keyword from UpdateListView, as you have done before. In test(), you need to instantiate Aa before you access UpdateListView.
Aa temp = new Aa()
You can then access the method by using
temp.UpdateListView(someArray);
Related
I’m trying to implement a simple singleton parent class for internal use (I only want to avoid static fields and don’t care about safety).
The reason I want a generic parent class is so I don’t have to worry about boilerplate and can simply inherit from Simpleton. I plan on having quite a few of these.
Here’s what I have:
class Simpleton
{
static Simpleton instance;
static Simpleton()
{
instance = new Simpleton();
}
// I know this naming isn’t ideal, but I’m going for brevity and I’m the only one using this codebase
static Simpleton I { get => instance; }
}
This works if I actually want to use an instance of Simpleton but I want to create a child class and use it:
class Settings : Simpleton
{
public int testSetting = 1;
}
// somewhere else
void Test()
{
// compiler error since Simpleton does not contain the field `testSetting`
var num = Settings.I.testSetting;
}
I just want to make the static Simpleton() function set instance to an instance of the child class. I can do this with reflection, but I can’t figure out how to do it such that the compiler knows that it is an instance of the child class.
I’m surprisingly stumped on how to make this work, and since my main goal is to have as little boilerplate as possible in the child class, I want to avoid overriding to whatever extent possible.
Make your Singleton a generic, and then derive Settings from Singleton<Settings>, like this:
var t = Settings.Instance.testSetting;
Console.WriteLine(t);
class Singleton<T> where T: new()
{
public static T Instance = new T();
}
class Settings : Singleton<Settings>
{
public int testSetting = 1;
}
I'm currently trying to get into C#, after doing a ton of Java. I wanted to pass my GUI Form to another class, but I run into some trouble trying to access its containers etc. from there.
This is the autogenerated Form class:
namespace Wecker
{
public partial class WeckerDesign : Form
{
public WeckerDesign()
{
InitializeComponent();
new WeckerRun(this);
}
}
}
and this is the recieving class:
namespace Wecker
{
class WeckerRun
{
WeckerDesign wdesign = new WeckerDesign();
public WeckerRun(WeckerDesign wdesign)
{
this.wdesign = wdesign;
new DisplayClock(wdesign);
}
}
}
However, when I am trying to access the container "clockfield" from the recieving class, I can't find it. However, in the passing class, I can easily get there with this.clockpanel. ... and so on.
The recieving class won't even suggest me that. In Java, I would simply pass down my class as a whole with "this" in order to have the exact same reference in the other class, which I can treat as if I would do it in the original class where I got that object reference from.
How do I do this in C#?
How is your "clockpanel" field or property defined? It will need to be public to be accessible from outside the class.
I have two classes that I'd like to keep in separate files.
namespace GridSystem
{
public class Grid
{
public void AddItem(GridItem item)
{
item.InformAddedToGrid();
}
}
}
namespace GridSystem
{
public class GridItem
{
public void InformAddedToGrid()
{
Debug.Log("I've been added to the grid");
}
}
}
How do I ensure no other classes are allowed to call InformAddedToGrid?
I'm trying to emulate Actionscript namespaces, which can be used on a method, in place of public, private, internal, etc. It doesn't exactly protect the method, but forces an extra step of including the namespace before the method can be accessed. Is there an alternative approach to this in C#?
If GridItem itself can be hidden from the outside world as well I would consider putting GridItem inside Grid as a nested class. That way it won't be visible outside of the class
http://www.codeproject.com/Articles/20628/A-Tutorial-on-Nested-Classes-in-C
Not that you should do this, you should do what TGH suggests, have a public interface for GridItem, and have gridItem nested in Grid (then have a factory method on Grid to create Items and use partial Grid class to have them in separate files).
Because there isn't a way of having friend methods ( you can do friend classes through InternalsVisibleToAttribute )
You COULD do this ( but don't... )
public partial class Grid
{
public void AddItem(GridItem item)
{
item.InformAddedToGrid();
}
}
public class GridItem
{
public void InformAddedToGrid()
{
if (new StackTrace().GetFrame(1).GetMethod().DeclaringType !=
typeof(Grid)) throw new Exception("Tantrum!");
Console.WriteLine("Grid called in...");
}
}
then
var g = new Grid();
g.AddItem(new GridItem()); // works
new GridItem().InformAddedToGrid(); // throws a tantrum...
A really ugly answer would be to make it private and use reflection.
Another ugly answer would be to make it throw an exception if the caller is wrong.
Both of these are much slower to execute than a normal call also.
I don't think there's a good answer. C# doesn't have friends.
IMHO the answer is simple: access modifiers are just there to remind the programmer of the intent of how public/private a class should be. Through reflection you can lift those barriers.
The usage you make of a class is all in your hands: if your class is meant to only be used in one place, make it so. If anything, if a class has a special way of being used, document it - put it in the XML comments.
That said, in this specific example I'd believe since the GridItem doesn't add itself to the grid, it's not its job to notify about it (what if "I've not been added to the grid"?). I think InformAddedToGrid belongs somewhere in your Grid class as a private method, where there's a concept of adding an item... assuming that's what AddItem(GridItem) really does.
You can do it as TGH suggested, with nested classes, except the other way around. Nest Grid within GridItem and make InformAddedToGrid private. Here I use a nested base class so the public API can remain the same. Note that no one outside of your assembly can inherit from GridBase because the constructor is internal.
public class GridItem
{
public class GridBase
{
internal GridBase() { }
public void AddItem(GridItem item)
{
item.InformAddedToGrid();
}
}
private void InformAddedToGrid()
{
Debug.Log("I've been added to the grid");
}
}
public class Grid : GridItem.GridBase { }
Another option is to have GridItem explicitly implement an internal interface. This way no one outside of your assembly can use the interface by name and therefore cannot call InformAddedToGrid.
public class Grid
{
public void AddItem(GridItem item)
{
((IGridInformer)item).InformAddedToGrid();
}
}
public class GridItem : IGridInformer
{
void IGridInformer.InformAddedToGrid()
{
Debug.Log("I've been added to the grid");
}
}
internal interface IGridInformer
{
void InformAddedToGrid();
}
Updated to reflect to my own source
I'm in process of building my first winform application in c# and I'm trying to figure out the best practice for structuring my classes to work smoothly when I use them in my forms.
I have a couple of examples which I will try to explain the best way i can.
When working with get/set variables in a class, the best practice should be something like this:
JobMove.cs
public class JobMove
{
private List<string> jobNames { get; set; }
public string Scanner;
public JobMove()
{
this.Scanner = Properties.Settings.Default.Scanner;
}
public void ListSelected(ListBox lbx)
{
foreach (string jName in this.jobNames)
{
lbx.Items.Add(jName);
}
}
public static List<string> GetCheckedJobs(ListView lw)
{
int countChecked = lw.CheckedItems.Count;
int itemCount = 0;
List<string> jList = new List<string>();
foreach (ListViewItem item in lw.CheckedItems)
{
JobInfo jobInfo = Job.Find(Convert.ToInt32(lw.Items[item.Index].SubItems[1].Text));
jList.Add(jobInfo.Name);
itemCount++;
}
return jList;
}
}
My problem is when I combine this with my forms and I call this, then I would try to do something like this:
MyForm1.cs
public partial class MyForm1 : Form
{
private void btnMoveJobs_Click(object sender, EventArgs e)
{
Properties.Settings.Default.Scanner = cbxScanners.SelectedItem.ToString();
JobMove moveJobs = new JobMove();
frmMoveJobs FrmMoveJobs = new frmMoveJobs();
FrmMoveJobs.ShowDialog();
}
}
MyForm2.cs
public partial class frmMoveJobs : Form
{
public frmMoveJobs()
{
InitializeComponent();
JobMove moveJobs = new JobMove();
lblFrom.Text = moveJobs.Scanner;
moveJobs.ListSelected(lbxJobsToMove);
cbxMjScanners.DataSource = System.Enum.GetValues(typeof(Scanners));
}
}
But when I call MyClass in MyForm2 and I want to call the DoSomethingElse method, then myString will be reset to a null value. And that makes sense to me, but how do I work around this?
I tried to figure out what to use here to get easier around these flaws in my code, but my knowledge is far too weak to just implement an easy solution.
I know I could just store this variable in Settings.settings as an example, but to me that just seems like a real overload for such a simple task.
I might just need a point in the right direction to right on what to do in this situation.
If you do a MyClass myClass = new MyClass(); then indeed - the values are independent and unrelated. If you want to share the MyClass instance then pass the MyClass instance between the forms. Perhaps:
using(var form2 = new Form2()) {
form2.SensibleName = existingMyClassInstance;
form2.ShowDialog();
}
(note the using above btw; when using ShowDialog() it is your job to make sure the form is disposed; it only gets disposed automatically if using Show())
Firstly, they're properties, not variables (the variables are the underlying data source).
Secondly, the whole point of get/set accessors is so you can get and set the value without needing helper methods.
Thirdly, and as to your problem, you're creating a new instance of the class in each form (hinted at by the new keyword) and the value of the property will be whatever it is initialised as on construction of the instance (or not.) i.e. the values of properties are not shared between different instances of the same type.
Think of the mold for a key: I can get multiple instances of the key cut from a "blueprint", but any damage that one suffers won't be reflected by the rest - they're unique in that sense.
If you want the forms to both access the same instance of that type, then you will need to stash the instance somewhere in your code which is accessible to both.
A few options:
Pass in an instance of MyClass in the form2's constructor.
Make MyClass a static property of either Form1 or Form2 and access it via that on the other form.
Make MyClass static (not recommended).
If you want to use the instance of MyClass created in MyForm1 inside of MyForm2, you need to provide it to MyForm2.
Something like this would work:
public partial class MyForm2 : Form
{
public MyForm2(MyClass given)
{
InitializeComponent();
given.DoSomethingElse();
}
}
Easy Solution:
private static string myString { get; set; }
Why: because you initialize the class again when initializing Form2 and it will create a new class. With the "static" keyword you create a property which is the same in all instances of this class.
BUT: please read some books before continuing, this would be the solution to this problem, but the source of many others. Try to understand C# and Forms first, than (or alongside with reading/learning) start coding!
this is because each of your form has a new object of "MyClass".
To achieve what you want to do use a static property... this won't be initialized and gives back the same value for each object of MyClass
it looks like this
public class MyClass {
public static string myString { get; set; }
public void ChangeMyString(string newString)
{
myString = newString;
}
public void DoSomethingElse()
{
MessageBox.Show(myString);
}
}
I'm trying to make a program in Visual C# that has my one created class, and at application launch it creates an array of my class object, and this array of my object can be used all over the program. So any function, or a control's event can access the array of objects and their member variables.
I created my class as "public" but for some reason i get these errors upon build:
"The name 'MyArrayObjectNameHere' does not exist in the current context"
When I try to access the objects member variables inside a load file dialog event in which I am trying to load data from a file into the member variables of the object array.
Is there a certain place the object array needs to be declared and constructed so it exists in every context? If so, can you tell me where this is?
I currently declare it in the main function before form1 is run.
My class definition looks like this in its own .cs file and the programs namespace:
public class MyClass
{
public int MyInt1;
public int MyInt2;
}
I declare the array of objects like this inside the main function before the form load:
MyClass[] MyArrayObject;
MyArrayObject = new MyClass[50];
for (int i = 0; i < 50; i++)
{
MyArrayObject[i] = new MyClass();
}
Thanks in advance for any help.
Your problem is that you are defining it within the main function, hence it will only exist inside the main function. you need to define it inside the class, not inside the function
public partial class Form1:Form
{
MyClass[] MyArrayObject; // declare it here and it will be available everywhere
public Form1()
{
//instantiate it here
MyArrayObject = new MyClass[50];
for (int i = 0; i
Only static objects are available in all contexts. While your design lacks... er, just lacks in general, the way you could do this is to add a second, static class that maintains the array of your MyClass:
public static class MyClassManager
{
private MyClass[] _myclasses;
public MyClass[] MyClassArray
{
get
{
if(_myclasses == null)
{
_myClasses = new MyClass[50];
for(int i = 0; i < 50;i++)
_myClasses[i] = new MyClass();
}
return _myclasses;
}
}
}
Do yourself a fav and grab CLR Via C# by Jeffrey Richter. Skip the first couple chapters and read the rest.
You need to make the array a static member of some class, .NET does not have a global scope outside of any class.
e.g.
class A
{
public static B[] MyArray;
};
You can then access it anywhere as A.MyArray
That't good.It is very useful for learners like me.