i have a class (say classA) that contains a string property.
i want to set it to a string property from another class (say classB) so that when i change the property into classA it changes in classB and visa versa.
i know i can do this with functions by using ref but when i try it on my class (Constructor) it doesn't work
here is what i have;
public class myClass
{
public string Name;
public int Image;
public myClass(ref string myName)
{
Name = myName;
}
public void changeIt()
{
Name = "xyz";
}
}
And my main code;
string myString = "abc";
Console.WriteLine("myString:"+myString);
myClass mClass = new myClass(ref myString);
mClass.changeIt();
Console.WriteLine("myString (After doThis):" + myString);
Console.ReadLine();
when i run it it produces;
myString:abc
myString (After doThis):abc
is there something i am missing here? why doesn't it change to xyz?
Generally speaking, a change in the state of an object should be communicated with an event.
So in the class that has the "important" property, when you change its value an event should be fired.
The other classes should be suscripted to this event and catch it.
You can add the value of the changed string to the fired event so that you won't even need to reference the object when the string value has changed.
You can see how events work in C# on this link.
An example of how to do it can be as follow:
class ClassWithImportantProperty
{
string myString = string.Empty;
public string MyImportantProperty
{
get { return myString; }
set
{
myString = value;
if (PropertyChanged != null)
PropertyChanged(myString, EventArgs.Empty);
}
}
public event EventHandler PropertyChanged;
}
class SecondClass
{
public string MyDependantString { get; set; }
public secondClass()
{
var classInstance = new ClassWithImportantProperty();
classInstance.PropertyChanged += classInstance_PropertyChanged;
}
void classInstance_PropertyChanged(object sender, EventArgs e)
{
MyDependantString = sender.ToString();
}
}
Basically you have a class that fires an event every time one of it's properties change.
Then another class that is suscribed to this event and every time it gets fired, it does some process of it's own.
Strings are immutable. What this means, is that when you "change" a string.. you're actually throwing away the old one and creating a completely new one. There is no getting around that without using some dodgy unsafe code. ("throwing away" in this context is.. forgetting about it.. allowing it to be cleaned up later by the Garbage Collector).
What this means in the context of your code, is that this:
Name = "xyz";
Creates a new string reference with the content xyz and assigns it to the reference Name. myString in the caller is unaffected by that.. it is a different reference.
As mentioned by #SimonWhitehead, strings are immutable. What you could do in this case, is to change your changeIt method to take an out parameter, and then pass in myString as the input, like so:
public void changeIt(out string myName)
{
myName = "xyz";
}
This will give you the output "xyz" after you make a call to this method as:
myClass.changeIt(out myString);
You are referencing a string into the constructor and changing its value in other method. So the ref keyword works only inside a block of code, constructor in this case.
This code will change the value myName to Name. But after constructor is called myName won't be referencing to a Name anymore. Note that you are assigning Name to ref myName and it won't reference to a Name.
public myClass(ref string myName)
{
myName = Name;
}
This will change the string as well:
public void changeIt(ref string myName)
{
Name = "xyz";
myName = Name;
}
I won't write about immutable because other guys already answered. You can do the trick with interfaces like so:
class Program
{
public interface IName
{
string Name { get; }
}
public class myClass : IName
{
public string Name { get; set; }
public myClass(string myName)
{
Name = myName;
}
public void changeIt()
{
Name = "xyz";
}
}
public class myClass2 : IName
{
private IName iname;
public string Name { get { return iname.Name; } }
public myClass2(IName myName)
{
iname = myName;
}
}
static void Main(string[] args)
{
myClass mClass = new myClass("abc");
myClass2 m2Class = new myClass2(mClass);
Console.WriteLine("myString:" + m2Class.Name);
mClass.changeIt();
Console.WriteLine("myString (After doThis):" + m2Class.Name);
Console.ReadLine();
}
}
It will actually do what you want to achieve.
To change the string, make the following changes in your code.
public string changeIt()
{
return "xyz"; //return a string from method
}
In the calling part
myString=mClass.changeIt(); //assign return value to myString
Related
using System;
public class NameChangeEventArgs : EventArgs
{
public string Name { get; private set; }
public NameChangeEventArgs(string name)
{
this.Name = name;
}
}
public class Dispatcher
{
private string _name;
public string Name
{
get
{
return _name;
}
set
{
OnNameChange(_name);
_name = value;
}
}
public event EventHandler<NameChangeEventArgs> NameChange;
protected virtual void OnNameChange(string name)
{
NameChange?.Invoke(this, new NameChangeEventArgs(name));
}
}
public class Handler
{
public void OnDispatcherNameChange(object Source, NameChangeEventArgs args)
{
Console.WriteLine("Dispatcher's name changed to {0}", args.Name);
}
}
class Program
{
static void Main(string[] args)
{
var dispatcher = new Dispatcher();
var handler = new Handler();
dispatcher.NameChange += handler.OnDispatcherNameChange;
var name = "Sidd";
dispatcher.Name = name;
}
}
The purpose of my code is to change Dispatcher's name to the name passed to it, but whilst this is done, an event is raised to run a method in the Handler class to display the name to which the Dispatcher has been changed to.
The "OnDispatcherNameChange(object Source, NameChangeEventArgs args)" is called to display the message "Dispatcher's name changed to " in my dispatcher's setter.
However it outputs this instead...
Dispatcher's name changed to
Press any key to continue...
What have I done wrong?
I think it's because you're raising the event before changing the property.
The code that receives the event will read the old name and not notice the new one.
Try doing this instead:
set
{
// First change the property
_name = value;
// Then raise the event
OnNameChange(_name);
}
I want to get value of TextBox in Form1, to another class.
I try to make a set and get, but I can't do this, because VS shows me error about ambiguity in code.
public partial class Form1 : Form
{
private TextBox _textBox1;
public Form1()
{
this._textBox1 = textBox1;
InitializeComponent();
}
public string _textBox1
{
get { return _textBox1.Text; }
set { _textBox1.Text = value; }
}
}
How to make this correct? My control is private.
You have one field and one property in you class with the same name, change the name of the property, for instance to
public string FormTextBox1
{
get { return _textBox1.Text; }
set { _textBox1.Text = value; }
}
as naming standard the public properties must be Pascal Case notation
Capitalization Conventions
You can pass textBox1.Text to a variable, and make a getter/setter for it.
Like this:
public class A : Form1
{
// assuming it's a string. If it's not, change the type
// for the getter method below accordingly
private string textBoxValue;
// at some point, you'll have to make this line below:
textBoxValue = textBox1.Value;
public string GetTextBoxValue()
{
return textBoxValue;
}
}
public class B
{
A aReference = new A();
// you can get the value you want by doing
// aReference.GetTextBoxValue();
}
public void yourFormLoadMethod()
{
//this instantiates a new object of your class
nameOfYourClass newYourObject = new nameOfYourClass(//put any params you need here);
txtNameOfYourTextBox.DataBindings.Add("Enabled", newLTDObjectBenInt, "YourTextBoxEnabled", true, DataSourceUpdateMode.OnPropertyChanged);
txtNameOfYourTextBox.DataBindings.Add("Value", newLTDObjectBenInt, "YourTextBoxEntered", true, DataSourceUpdateMode.OnPropertyChanged);
txtNameOfYourTextBox.DataBindings.Add("Visible", newLTDObjectBenInt, "YourTextBoxVisible", true, DataSourceUpdateMode.OnPropertyChanged);
}
public class nameOfYourClass
{
//constructor
public nameOfYourClass(//same params here from the Load method)
{
//place any logic that you need here to load your class properly
//this sets default values for Enable, Visible and the text
//you use these fields to manipulate your field as you wish
yourTextBoxVisible = true;
yourTextBoxEnabled = true;
yourTextBoxEntered = "this is the default text in my textbox";
}
private bool yourTextBoxEnabled;
public bool YourTextBoxEnabled
{
get
{
return yourTextBoxEnabled;
}
set
{
yourTextBoxEnabled = value;
}
}
private bool yourTextBoxVisible;
public bool YourTextBoxVisible
{
get
{
return yourTextBoxVisible;
}
set
{
yourTextBoxVisible = value;
}
}
private string yourTextBoxEntered;
public string YourTextBoxEntered
{
get
{
return yourTextBoxEntered;
}
set
{
yourTextBoxEntered = value;
}
}
}
I get this error on the setter line
"An unhandled exception of type 'System.StackOverflowException' occurred in WebFormsApplication1.dll"
What is an elegant way to manipulate Property1 which I added getter and setter for in a Master page (please see below),
then I attempted to manipulate it in method1() and finally call method1() inside onInit.
namespace WebFormsApplication1
{
public partial class SiteMaster : MasterPage
{
public string Property1
{
get
{
return System.Configuration.ConfigurationSettings.AppSettings["key1"];
//gets value from config file where pair key-value is stored
}
set
{
Property1 = value;
}
}
public void method1()
{
Property1 = Property1 + "stringToAppend"; // manipulate property here
}
protected void Page_Init(object sender, EventArgs e)
{
method1();
.....
}
}
}
In the Site.Master.aspx I have <%= Property1 %>
If I don't add the setter the property is read only. Maybe I should manipulate it inside the setter?
I was hoping to be able to do it separately for increased modularisation.
Thanks
the problem is here:
set
{
Property1 = value;
}
You can't do it because recursion occurs here and no condition to exit, you can't set this property in his own setter, you should have some field and set it in setter:
public string someValue = System.Configuration.ConfigurationSettings.AppSettings["key1"];
public string Property1
{
get
{
return someValue;
}
set
{
someValue = value;
}
}
Or you can use auto-property:
C# 6:
public string Property1 {get;set;} = System.Configuration.ConfigurationSettings.AppSettings["key1"];
Or lower than C# 6 - you should declare you property and initialize it in contructor or method:
public string Property1 {get;set;}
public void ConstructorOrMethod()
{
Property1 = System.Configuration.ConfigurationSettings.AppSettings["key1"];
}
I'm sure this has been asked before I just don't know the correct way to word it so I can't find what I am looking for.
I have a class with a field which I want to be able to see from the outside, just not be able to modify it directly..
public class myclass
{
public int value;
public void add1()
{
value = value + 1;
}
}
So I would really like to only have the 'value' field modifiable from the method add1() but I still want to be able to see the value of 'value'.
EDIT: I was thinking only modifiable via the class myclass, but I typed otherwise. Thanks for pointing that out.
public int value { get; private set; }
You cannot make it modifiable only by the method add1, but you can make it only modifiable by myclass.
See this:
https://msdn.microsoft.com/en-us/library/75e8y5dd.aspx
Please consider the following options to encapsulate a field (i.e. provide an "interface" for the private field value):
Provide the public method (accessor):
// ...
private value;
// ...
public void Add()
{
++value;
}
public int GetValue()
{
return value;
}
Provide the public property (only accessor):
// ...
private value;
// ...
public void Add()
{
++value;
}
public int Value
{
get { return value; }
}
Provide the auto-implemented property (public accessor, private mutator):
// ...
// The field itself is not needed: private value;
// ...
public void Add()
{
++Value;
}
public int Value { get; private set; }
It is worth noting that some IDEs or IDE–plugins provide the appropriate refactoring called "Encapsulate Field".
You can use public property without setter to just see the value from outside. make the value private so its only visible inside the calss.
public class myclass
{
private int value;
public void add1()
{
value = value + 1;
}
public int Value
{
get
{
return value;
}
}
}
I have to bind my GUI to the interface:
public interface IMain
{
public CTopObject MyObject { get; }
public CInsideObject MidObj { get; }
public CInsideObject MyCollectionObject { get; }
}
Objects definitions:
public class CMain
{
public CTopObject MyObject { get { return this.myObject; }
public CInsideObject MidObj { get { return this.MyObject.SomeObject; } }
public CInsideObject MyCollectionObject
{ get
{
if(this.MyObject.Thedict.Contains(0))
return this.MyObject.TheDict[0];
else
return default(CInsideObject);
}
} //0 is ofcourse an example
}
public class CTopObject
{
private string someString;
public string SomeString
{
get { return this.someString; }
set
{
this.someString = value;
if(this.PropertyChanged!=null) this.PropertyChanged(this, "SomeString");
}
}
private ObservableDictionary int, CInsideObject> theDict; //how to open bracket on stackoverflow? ;)
public ObservableDictionary int, CInsideObject> TheDict
{
get { return this.theDict; }
}
private CInsideObject someObject;
public CInsideObject SomeObject
{
get { return this.someObject; }
}
//There is constructor. After that, there is init method,
//that creates new thread. The thread updates SomeString,
//representing object state. After thread raise specified event
//callback method begin to initialize SomeObject and
//after callback from SomeObject it adds some objects to
//TheDict, and initialize them.
}
public class CInsideObject : INotifyPropertyChanged
{
private string someString;
public string SomeString
{
get { return this.someString; }
set
{
this.someString = value;
if(this.PropertyChanged!=null) this.PropertyChanged(this, "SomeString");
}
}
//There is constructor, and init method that creates new thread.
//This thread updates SomeString that represents actual state of object.
}
Now in my application main.xaml.cs file, I have field
private IMain theMain;
Then I set DataContext of my window to IMain field:
theMain = new CMain(... some args ...);
this.DataContext = this.theMain;
...initialize theMain...
in XAML it looks like this:
Label Content="{Binding Path=MyObject.SomeString}" Name="label1"/>
Label Content="{Binding Path=MyMidObj.SomeString}" Name="label2"/>
Label Content="{Binding Path=MyCollectionObject.SomeString}" Name="label3"/>
Initialization like I wrote is mostly in other threads than main app thread. Still, in every "state object" there is SomeString property, which calls NotifyPropertyChanged event. SomeString is updated whenever thread change object state. Window GUI has some labels that represents SomeString of proper objects.
I don't know why only MyObject of IMain interface is updating binded label when SomeString of TopObject changes. Labels for MidObj and MyCollectionObject are empty somehow.
Sorry for my english, I hope my question is not to confusing ;)
Thanks
Joe
what happens if you set your binding to:
Label Content="{Binding Path=MyObject.SomeObject.SomeString}" Name="label2"/>
Label Content="{Binding Path=MyObject.TheDict}" Name="label3"/>