I have to create a class in C#, call it Class1. This class must contain an enum field, called Flag. Flag has 4 possible values, say A,B,C,D. An instance of Class1 can contain another instance of Class1 where the state of Flag is different from A.
My question is: how to formulate the condition that the state of Flag in the sub-instance must be different from A?
Mark your Class1 "subinstance" as private and make it accessible only through a property. In the property setter, check that the value which is set has the flag different from the one of the parent. Be careful, if the parent Class1 flag must always be different from the child, then you also have to add a check when setting the parent flag.
You could make the setter private and check it in the constructor, you also have to provide a private constructor for the inner instance. So basically an immutable class:
public enum Flag
{
A, B, C, D
}
public class Class1
{
private Class1 _Class1Inner;
public Class1 Class1Inner
{
get { return _Class1Inner; }
private set { _Class1Inner = value; }
}
private Flag _Flag;
public Flag Flag
{
get { return _Flag; }
private set { _Flag = value; }
}
// used only to create the inner instance
private Class1(Flag innerFlag)
{
this.Flag = innerFlag;
_Class1Inner = null; // or whatever
}
public Class1(Flag flag, Flag innerFlag)
{
if (innerFlag == Flag.A)
throw new ArgumentException("innerFlag must not be Flag.A!", "innerFlag");
this.Flag = flag;
this.Class1Inner= new Class1(innerFlag);
}
}
If you want this class to be mutable, so that you can change the Flag after creation, you have to remember whether it is an inner instance or not.
Therefore you need another field which you can set from the constructor:
public class Class1
{
private bool _isInnerInstance = false;
private Class1 _Class1Inner;
public Class1 Class1Inner
{
get { return _Class1Inner; }
private set { _Class1Inner= value; }
}
private Flag _Flag;
public Flag Flag
{
get { return _Flag; }
set
{
if (_isInnerInstance && value == Flag.A)
throw new ArgumentException("innerFlag must not be Flag.A!", "innerFlag");
_Flag = value;
}
}
private Class1(Flag innerFlag)
{
this.Flag = innerFlag;
_isInnerInstance = true;
_Class1Inner = null; // or whatever
}
public Class1(Flag flag, Flag innerFlag)
{
if (innerFlag == Flag.A)
throw new ArgumentException("innerFlag must not be Flag.A!", "innerFlag");
this.Flag = flag;
_Class1Inner = new Class1(innerFlag);
}
}
Now following is not allowed:
Class1 cls1 = new Class1(Flag.A, Flag.B);
cls1.Class1Inner.Flag = Flag.A; // throws an ArgumentException at runtime
Started as a comment, but a bit too detailed so moved to answer...
On first though then, I would say that Class1 needs a way of knowing it is a 'sub-instance', for example you could force a constructor that defines this:
private IsSub { get; set; }
public Class1(bool isSub)
{
IsSub = isSub;
}
which sets a property in the class. This property can be used to check if the Flag can have A or not. But you will need a way to validate when the flag is set. For that you could add a validation method that throws an error to the property setter:
private Flag myFlag;
public Flag MyFlag
{
get { return myFlag; }
set { ValidateFlag(value); myFlag = value; }
}
void ValidateFlag(Flag flag)
{
if(IsSub && flag == Flag.A)
throw new Exception("Invalid flag");
}
Finally, you need to decide when to set the sub-instance. If you only want to allow one level of subinstance (so child class won't have their own child instances) then you can do it in the default constructor like so:
public Class1 ChildClass { get; set; }
public Class1()
{
ChildClass = new Class1(true);
}
(You also will want to think about how the default values for the flag properties are going to be set, but that is your logic to decide on.)
Here is example usage:
Class1 myClass = new Class1();
myClass.MyFlag = Flag.A; // This is fine.
myClass.SubClass.MyFlag = Flag.A; // This will throw an exception.
Related
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'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 my Control.When I change the properties of the control. I get this:
this.myLabel1.BorderShadow = true;
this.myLabel1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
And I need to get this:
this.myLabel1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.myLabel1.BorderShadow = true;
How to do so is done automatically in Form.Desinger.cs ?
If you say Why?
private bool BorderShadow_ = false;
public bool BorderShadow
{
get
{
return BorderShadow_;
}
set
{
if (Border_Style_ == BorderStyle.FixedSingle)
{
BorderShadow_ = value;
}
else
{
throw new ArgumentOutOfRangeException("BorderShadow", "BorderShadow can be true if BorderStyle=FixedSingle");
}
}
}
You could look into the ISupportInitialize interface. It allows you to skip the validity check when initializing your controls. For example (adapted from one of my projects):
public class MyControl : Control, ISupportInitialize
{
private bool _created = true;
public void BeginInit()
{
_created = false;
}
public void EndInit()
{
_created = true;
//check all your properties here too
}
private bool BorderShadow_ = false;
public bool BorderShadow
{
get
{
return BorderShadow_;
}
set
{
BorderShadow_ = value;
if (_created && Border_Style_ != BorderStyle.FixedSingle)
throw new ArgumentOutOfRangeException();
}
}
}
If I remember correctly, the VS designer will automatically add calls to BeginInit and EndInit for you as well.
I think they will appears in the same order as they are defined. So you can override with new old setting:
public new BorderStyle BorderStyle
{
get {return base.BorderStyle;}
set {base.BorderStyle = value;}
}
and then declare your BorderShadow setting.
The designer will always order the properties alphabetically and this can't be changed.
The sense of a property is that it is side effect free and that it can be changed at any time in any order. This means that if you have multiple properties which representing some kind of complex state and not all combinations are making sense, this error should not be reported while switching the property itself.
So to accomplish these problems you have two possibilities:
Like #Andrew already mentioned implement ISupportInitialize and take care if you are within this state.
Within the property setter call a method that checks if all settings currently made are making sense and perform the desired action only in this case:
public class MyControl : Control
{
private bool _BorderShadow;
private BorderStyle _BorderStyle;
public bool BorderShadow
{
get { return _BorderShadow; }
set
{
if(_BorderShadow != value)
{
_BordeShadow = value;
ApplyBorderShadowIfNeeded();
}
}
}
public BorderStyle BorderStyle
{
get { return _BorderStyle; }
set
{
if(_BorderStyle != value)
{
_BorderStyle = value;
ApplyBorderShadowIfNeeded();
}
}
}
private void ApplyBorderShadowIfNeeded()
{
if(_BorderStyle == BorderStyle.FixedSingle
&& _BorderShadow)
{
// ToDo: Apply the shadow to the border.
}
}
}
I have a class that contains two other objects.
A variable in the first object bind to WPF element, call it X.
A similar variable in the other object.
I want that when the PropertyChanged event happens, it will change the variable in the second object.
Here is the code that does not work for me:
The class that contains the variables: (I had register to property changed event)
private Class1 _var1;
public Class1 Var1
{
get { return _var1; }
set
{
_var1= value;
if (_var1!= null)
_var1.PropertyChanged += new PropertyChangedEventHandler(_var1_PropertyChanged);
else
_var1.PropertyChanged -= new PropertyChangedEventHandler(_var1_PropertyChanged);
}
}
void _var1_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if(e.PropertyName=="X")
Var2.X= Var1.X;
}
private Class2 _var2;
public Class2 Var2
{
get { return _var2; }
set { _var2= value; }
}
Class 1:
private int _x;
public int X
{
get { return _x; }
set
{
if (_x!= value)
{
_x= value;
NotifyPropertyChanged("X");
}
}
}
class 2:
public int X { get; set; }
PropertyChanged work in class 1 but he did not come to an event I created in a class that contains the two variables, why?
I'm not sure I understand exactly what you mean, but if I had a class with 2 variables that I wanted to change together, I would try the following:
First, define some SetAndNotify method or you'll get a headache from the PropertyChanged events:
public void SetAndNotify<T>(ref T field, T value, Expression<Func<T>> exp)
{
if (!Equals(field, value))
{
field = value;
OnPropertyChanged(exp);
}
}
Add it to some base class that will handle this event.
Second, in your setter for Var1 you register for the change event and not set anything, is that on purpose?
Third and last, there's no problem with changing more than one property in a setter, but make sure it's the public property that you change:
private SomeType privateVar1;
public SomeType PublicVar1
{
get { return privateVar1; }
set
{
SetAndNotify(ref privateVar1, value, () => PublicVar1);
MyOtherPublicVar = someNewValue; // this will activate the property's setter.
}
}
I hope this helps. If not, please try to clarify your question.
I've defined a class with the following property:
private ObservableCollection<Job> allJobs;
Access is defined as follows:
public ObservableCollection<Job> AllJobs
{
get
{
return this.allJobs;
}
set
{
this.allJobs = value;
}
}
The get set works fine when I assign a whole ObservableCollection to the property, the set works fine for retrieving it obviously. But why have I lost all the methods that normally allow me to 'Add' (i.e. add 1 job to the collection)?
At the moment I'm having to create a temporary collection to populate to then assign to the allJobs property and I shouldn't have to.
Any ideas??
What do you mean with 'lost methods'? Have you tried AllJobs.Add()? The following code works for me:
void Main()
{
AllJobs = new ObservableCollection<Job>();
AllJobs.Add(new Job());
}
public class Job { }
private ObservableCollection<Job> allJobs;
public ObservableCollection<Job> AllJobs
{
get
{
return this.allJobs;
}
set
{
this.allJobs = value;
}
}
EDIT:
Based on your comment I've amended my code as follows but everything still works for me, I have noticed however that you don't seen to initialise the allJobs collection anywhere.
void Main()
{
PresentationManager.Instance.AllJobs.Add(new Job());
}
public class Job { }
sealed class PresentationManager
{
public static readonly PresentationManager Instance = new PresentationManager();
private PresentationManager()
{
allJobs = new ObservableCollection<Job>();
}
private ObservableCollection<Job> allJobs;
public ObservableCollection<Job> AllJobs
{
get { return this.allJobs; }
set { this.allJobs = value; }
}
}
Normally you wouldn't want a setter for such a property, as you would lose all events bound to the ObservableCollection when the setter is used.
public ObservableCollection<Job> AllJobs { get; private set; }