How do I get notified when an array property changes? - c#

My class contain many properties and i need to handle each properties.
See this below:
public partial class my_form : Form
{
private Image[] _imagelist;
public Image[] imagelist
{
get
{
return _imagelist;
}
set
{
this._imagelist = value;
this.on_imagelist_changed();
}
}
private void on_imagelist_changed()
{
// do something.
}
private void button1_Click(object sender, EventArgs e)
{
/* set new imagelist */
this.imagelist = getimagelist();
}
}
Yes, It's work fine.
But when i call like this.
public partial class my_form
{
private void listView1_MouseDoubleClick(object sender, MouseEventArgs e)
{
int selectedIndex = this.listView1.SelectedItems[0].ImageIndex;
this.imagelist[selectedIndex] = dosomething(this.imagelist[selectedIndex]);
}
}
It's don't call on_imagelist_changed(). Why ?
I can't add property by indexer like this. :(
public partial class my_form
{
public Image imagelist[int x]
{
get
{
return _imagelist[x];
}
set
{
this._imagelist[x] = value;
this.on_imagelist_changed();
}
}
}
Can anyone help me solve this problem ?
Can i avoid to make a control class like this C# Indexers ?
I founded some suggestion, they told me let try ObservableCollection. I don't understand about this. May be someone example for me ?

It's don't call on_imagelist_changed(). Why?
Because, quite bluntly, imageList has not changed. Some images inside imageList may have changed, but your code reacts only to the change of the entire imageList. The assignment calls get of your property twice; it never calls the setter.
I can't add property by indexer like this.
That's correct. However, you correctly noted that you could use an observable collection:
public ObservableCollection<Image> Images {get;}
private void OnImageListChanged(
object sender
, NotifyCollectionChangedEventArgs e) {
// do something.
}
public MyForm() {
Images = new ObservableCollection<Image>();
Images.CollectionChanged += OnImageListChanged;
}

Because your property gets and sets pointer to array, not array itself. So when you change array items pointer stays the same.
That's why properties should not return arrays.

Related

I want to link two variables by ref so as when I update one variable the other updates also

I want to assign one variable to another by reference so as when one variable updates so does the other.
I have a series of variables that I need to update based on something that a piece of hardware I am connected to is doing. I have set up an object array and am assigning each of my variables to an index in the object array. It is the object array that gets updated but when this happens I want the property setter for my original variable to fire so as I can do something. The reason for the object array is so as I can iterate through it in a loop and because my original variables can be of different types. I have shown an overly simplified version of what I am trying to do below, I hope it makes sense.
Edit: Just to note that the items in the testVars array are being updated elsewhere, I have just shown a simplified version of what I am trying to do below.
public partial class Form1 : Form
{
private bool _test0 = false;
private int _test1 = 0;
public object[] testVars = new object[2];
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
testVars[0] = test0;
testVars[1] = test1;
}
public bool test0
{
get
{
return _test0;
}
set
{
_test0 = value;
UpdateTest0();
}
}
private void UpdateTest0()
{
bool NewTest0 = _test0;
}
public int test1
{
get
{
return _test1;
}
set
{
_test1 = value;
UpdateTest1();
}
}
private void UpdateTest1()
{
int NewTest1 = _test1;
}
}
One solution I thought might work for me was to use pointers but because the variable declaration and pointer creation must be in different scope in my application this will not work. Also everything I have read on forums has suggested that pointers should not be used.
# Michael Ceber, many thanks for the prompt response. I think I understand what you mean and have updated my example code accordingly but it still does not behave as I want. My updated code is as follows
namespace VariableLinks
{
public partial class Form1 : Form
{
private bool _test0 = false;
private int _test1 = 0;
public ObjectX[] testVars = new ObjectX[2];
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
testVars[0] = new ObjectX();
testVars[0].val = test0;
testVars[1] = new ObjectX();
testVars[1].val = test1;
}
public bool test0
{
get
{
return _test0;
}
set
{
_test0 = value;
UpdateTest0();
}
}
private void UpdateTest0()
{
bool NewTest0 = _test0;
}
public int test1
{
get
{
return _test1;
}
set
{
_test1 = value;
UpdateTest1();
}
}
private void UpdateTest1()
{
int NewTest1 = _test1;
}
private void button1_Click(object sender, EventArgs e)
{
testVars[0].val = true;
}
}
public class ObjectX : object
{
public object val = new object();
}
}
Now when my button click event fires and updates testVars[0].val I expect the setter for test0 to fire but it doesn't. I assume I have misunderstood what you meant?
If you store objects or reference types to objects in your array, i.e not value types like int, bool etc, which contain the values, then this will help.
e.g if your object 'objectx' has a property called value then objectx.value can store such a value.
Then you can set any variables you like to this objectx and whenever you update the value of objectx.value all variables will pickup the change, as they are all pointing to the same object...
So in your example
testVars[0] = test0;
testVars[1] = test1;
this would become
testVars[0].value = test0;
testVars[1].value = test1;
maybe to achieve this
public object[] testVars = new object[2];
should become
public ObjectX[] testVars = new ObjectX[2];
and add the single public property 'value' to this ObjectX class...
Hope that makes sense!

How to call value from getter and setter method

I have a class called nyoba, i tried to enter value of textBox1.Text to eek.konsentrasi.
And I don't have any idea to call value of eek.konsentrasi from another class. Anybody knows? please help me.
public class nyoba
{
private string Konsentrasi;
public string konsentrasi
{
get
{
return Konsentrasi;
}
set
{
Konsentrasi = value;
}
}
public void njajal(string hehe)
{
}
}
private void button1_Click(object sender, EventArgs e)
{
nyoba eek = new nyoba();
eek.konsentrasi = textBox1.Text;
}
public class caller
{
//how to get eek.konsentrasi variable?
}
As first, your class names should always be pascal case (first letter uppercase). Also your public property should be pascal case.
Then your Nyoba class and its property Konsentrasi are not static, means you have to initiate the class as object before you can access it's non static property.
Nyoba n = new Nyoba();
string s = n.Konsentrasi;
To access the same instance you should not create the instance inside of the button click event. Place your Nyoba instance somewhere you can access to in the form and in the Caller class.

Access components c#

I'm wondering about why can I access text from, for example, a combobox from outside the main class. But I can't add items to it.. the modifier of my combobox is set to public
public class ImageManager : mainFrame // Where my components are located
{
public ImageManager()
{
}
public void getText()
{
Console.WriteLine(comboBox.Text); //Will perfectly retrieve the text from it
}
public void setItem()
{
comboBox.Items.Add("Items"); //Does absolutely nothing and doesn't show error
}
}
Thanks for help !
What if your setItem() populated a ComboboxItem and added it instead of just text?
public void setItem()
{
ComboboxItem addMe = new ComboboxItem();
addMe.Text = "your text here";
addMe.Value = 1234; // make a relevant value
comboBox.Item.Add(addMe);
}
I see you got it working, great. But just in case your still scratching your head...
private void Form1_Load(object sender, EventArgs e)
{
ImageManager im = new ImageManager();
im.Show();
im.setItem();
}
ImageManager inherits from Form2 which has the comboBox. Seemed to work fine. comboBox got populated.

Linking a Text Box to a variable?

I would like to have direct access to the text inside a textbox on another form, so I added a public variable _txt to a form and added an event like so:
private void richTextBox1_TextChanged(object sender, EventArgs e)
{
_txt = richTextBox1.Text;
}
But the form is loaded like this:
public FrmTextChild(string text)
{
InitializeComponent();
_txt = text;
richTextBox1.Text = _txt;
Text = "Untitled.txt";
}
Is there a better way to directly link the two?
You could use a property instead to read directly from your TextBox. That way you don't need an extra variable at all.
public string Text
{
get
{
return richTextBox1.Text;
}
}
Add a setter if you also want to be able to change the text.
I don't think you should ever have forms reference each other's controls: when you change the lay out of one you will have to rewrite the code for the other. It is much better IMHO to store shared values in a separate class and have both forms reference that. Like so:
public class DataContainer
{
public string SomeData{get;set;}
}
public class Form1:Form
{
private DataContainer _container;
public Form1(DataContainer container)
{
_container=container;
}
private void richTextBox1_TextChanged(object sender, EventArgs e)
{
_container.SomeData = richTextBox1.Text;
}
private void SpawnForm2()
{
var form2=new Form2(_container);
form2.Show();
}
public class Form2:Form
{
private DataContainer _container;
public Form2(DataContainer container)
{
_container=container;
}
}
Another way to do it would be setting the Modifiers property for the TextBox (or any other control you want to access) to Protected Internal and then open the second form, the Owner being the first form.
This way, you can later on access the control and its properties with something like this:
((Form1)this.Owner).textBox1.Text = "This is a message from the second form";

.NET Collections and Accessing Object Methods

I'm completely new to GUI programming and need a little help with a list of pictureboxes.
The idea is that I have a list of pictureboxes. When a user clicks on one I want to (for example) change the BorderStyle property of the one selected to be Fixed3D, but change the remaining collection borders to FixedSingle (or something like that). What's the proper way to do something like this? I guess the bigger picture is how do I get a method of one class to call a method of another without having any information about it?
class myPicture
{
private int _pictureNumber;
private PictureBox _box;
public myPicture(int order)
{
_box = new List<PictureBox>();
_box.Click += new System.EventHandler(box_click);
_pictureNumber = order;
}
public void setBorderStyle(BorderStyle bs)
{
_box.BorderStyle = bs;
}
public void box_click(object sender, EventArgs e)
{
//here I'd like to call the set_borders from myPicturesContainer, but I don't know or have any knowledge of the instantiation
}
}
class myPicturesContainer
{
private List<myPicture> _myPictures;
//constructor and other code omitted, not really needed...
public void set_borders(int i)
{
foreach(myPicture mp in _MyPictures)
mp.setBorderStyle(BorderStyle.FixedSingle);
if(i>0 && _MyPictures.Count>=i)
_MyPictures[i].setBorderStyle(BorderStyle.Fixed3d);
}
}
You will need to create a Clicked event in your myPicture class and raise that event when it is clicked. Then you will need to attach to this event in your myPicturesContainer for each instance of myPicture that you have.
Here is a very simple example of what I mean:
class myPicture
{
public event Action<Int32> Clicked = delegate { };
private int _pictureNumber;
public void box_click(object sender, EventArgs e)
{
this.Clicked(this._pictureNumber);
}
}
class myPicturesContainer
{
private List<myPicture> _myPictures;
public void set_borders(int i)
{
foreach (myPicture mp in _myPictures)
{
mp.Clicked += pictureClick;
}
}
void pictureClick(Int32 pictureId)
{
// This method will be called and the pictureId
// of the clicked picture will be passed in
}
}

Categories