I create a user control like below:
public partial class TestControl : UserControl
{
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public State MyState
{
get { return new State(this); }
}
internal int[] _internalStates;
[TypeConverter(typeof(ExpandableObjectConverter))]
public struct State
{
private TestControl _myControl;
public State(TestControl _) { _myControl = _; }
public int Data
{
get { return _myControl._internalStates[0]; }
set { _myControl._internalStates[0] = value; }
}
}
}
Then I can drag the control from toolbox and modify the Data value in the designer.
The problem is the designer will generate this code in InitializeComponent method:
this.testControl1.MyState.Data = 0;
But this line will throw an error:
Cannot modify the return value of 'TestControl.MyState' because it is not a variable
I understand why the statement is error, the question is how can I control the code generation to correct the error, for example to generate code like this?
var myState = this.testControl1.MyState;
myState.Data = 0;
More information
State struct is just a bridge to modify the internal property in TestControl
So I want to keep State as a struct to avoid GC overhead.
The reason for not define property in TestControl class is there are multiple states in the class, and a state will contain multiple properties, so I need to wrap the modification methods rather than define a lot of properties in the TestControl class.
Why a compile time error for Control.StructProperty.Member = Value;?
Consider the following statement
this.Control.StructProperty.Value = 0;
StructProperty is a property, so first its getter will execute and since it's a structure and is a value type, it will return a copy of the struct and setting a property for that copy is not useful/working. The knows about the situation well and instead of compiling a confusing non-working code, it generates Compiler Error CS1612:
Cannot modify the return value of 'expression' because it is not a
variable
How can I generate a working code for a Struct property?
You probably have noticed that you cannot assign this.Size.Width = 100 with the same reason. And the way that form generates the code for Size property is:
this.Size = new Size(100,100);
You also can generate code for the property the same way, by implementing a type descriptor by deriving from TypeConverter returning an InstanceDescriptor in its ConvertTo method to generate the code for your structure property using a parametric constructor which you should have for the struct.
In general, I suggest using classes rather that structures for such property.
Related
I am setting up Coded UI Tests for WPF application and I want to use code approach instead of record-and-generate-code approach. I'd like to use page objects trough code and I need to declare control (buttons, tabs, etc.) variables in page objects that would be used by multiple functions.
I tried declaring the variable in a class and adding properties in constructor (pendingButton1)
and creating function which returns the control and assigning to a variable in a class (pendingButton2) but neither worked.
It works when I declare the variable (or create the variable by function) within the function that I want to use the variable in (pendingButton3 and 4).
public partial class Press : Header
{
WpfToggleButton pendingButton1 = new WpfToggleButton(_wpfWindow);
WpfToggleButton pendingButton2 = Controls.Press.getPendingButton(_wpfWindow);
public Press(WpfWindow wpfWindow):base(wpfWindow)
{
this.pendingButton1.SearchProperties[WpfControl.PropertyNames.AutomationId] = "Tab1Button";
}
public void clickPendingButton() {
WpfToggleButton pendingButton3 = new WpfToggleButton(_wpfWindow);
pendingButton3.SearchProperties[WpfControl.PropertyNames.AutomationId] = "Tab1Button";
WpfToggleButton pendingButton4 = Controls.Press.getPendingButton(_wpfWindow);
Mouse.Click(pendingButton1); //UITestControlNotFoundException
Mouse.Click(pendingButton2); //UITestControlNotFoundException
Mouse.Click(pendingButton3); //This works
Mouse.Click(pendingButton4); //This works
}
}
I'd like to make it work when I declare the pendingButton outside clickPendingButton() function since it is used in multiple other functions.
The helper function Controls.getWpfButton() return just properties of the button, not "real" button. It has to be used in a constructor, then it can be used anywhere within the class. I wouldn't say its best practice but it works for me.
Press.cs
public partial class Press : SharedElements
{
private WpfButton pendingButton;
public Press(WpfWindow wpfWindow):base(wpfWindow)
{
pendingTab = Controls.getWpfButton(_wpfWindow, "Tab1Button");
}
public void clickPendingButton() {
Mouse.Click(pendingButton);
}
}
Controls.cs
internal static WpfButton getWpfButton(WpfWindow wpfWindow, string AutomationId)
{
WpfButton button = new WpfButton(wpfWindow);
button.SearchProperties[WpfControl.PropertyNames.AutomationId] = AutomationId;
return button;
}
What you want appears to be exactly the sort f code that the Coded UI record and generate tool generates. It creates many pieces of code that have a structure of the following style:
public WpfToggleButton PendingButton
{
get
{
if ((this.mPendingButton == null))
{
this.mPendingButton = new WpfToggleButton( ... as needed ...);
this.mPendingButton.SearchProperties[ ... as needed ...] = ... as needed ...;
}
return this.mPendingButton;
}
}
private WpfToggleButton mPendingButton;
This code declares the button as the class property PendingButton with a private supporting field that has an initial and default value of null. The first time that property is needed the get code executes the required search and saves the found control in the private field. That value is then returned in each subsequent usage of the property. Note that assigning null to the supporting field can be done to cause a new search, as demonstrated in this Q&A.
So, my question is about the exact methodology behind windows form data binding.
I wrote a simple code, where i created a View, an IViewModel interface and a ViewModel.
interface IVM
{
}
and
public class Vm : IVM
{
int number;
public int Number
{
get
{
return this.number;
}
set
{
this.number = value;
}
}
}
the form looks like:
public partial class Form1 : Form
{
private IVM vm;
public Form1()
{
InitializeComponent();
this.vm = new Vm();
this.iVMBindingSource.DataSource = this.vm;
}
}
and the related designer part is:
this.textBox1.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.iVMBindingSource, "Number", true));
...
this.iVMBindingSource.DataSource = typeof(WindowsFormsApplication1.IVM);
You can clearly see that IViewModel interface does not publish a Number property, but the concrete ViewModel class has a Number property.
Although in design time i can't use the designer to bind the property (since IVM has no Number prop), i can manually write "iVMBindingSource - Number" into the textbox's Test property, to bind it.
My question is, how does binding work EXACTLY? Why don't I receive a runtime error, while trying to access IVM's not existing Number property?
(I tested and it actually changes the VM's Number prop properly)
Does it use some kind of reflection? How does this "magic" binding string works?
Thanks for your answers!
Jup it's done by reflection. I just checked the code and the binding is done by the Binding class. There is a method called CheckBindings which ensures the property you want to bind on is available. It basically works like this:
if (this.control != null && this.propertyName.Length > 0)
{
// ...certain checks...
// get PropertyDescriptorCollection (all properties)
for (int index = 0; index < descriptorCollection.Count; ++index)
{
// select the descriptor for the requested property
}
// validation
// setup binding
}
As Ike mentioned, you can find the source code here:
http://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/Binding.cs,3fb776d540d0e8ac
MSDN Reference: https://msdn.microsoft.com/en-us/library/system.windows.forms.binding(v=vs.110).aspx
As derape already mentioned, Binding uses reflection. It must use reflection because it cannot know anything about the class you are using. The evaluation will be done at runtime. Since your concrete type Vm got the specified property Number, reflection will return it and Binding class is satisfied. Binding is really flexible as long as the property name is valid.
On the other hand, when you are using the designer, it cannot know which concrete type you will use. Therefore it only allows you to use properties of the common base IVM. If you enter the string manually, design time evaluation will be skipped and input is passed to the binding constructor.
If you want to use designer support, just use the the concrete type or if you don't know the concrete type but need the property Number, simply create a new interface and derive from IMV.
public List<ObjectA> ObjectAList
{
get
{
return ObjectAList ?? new List<ObjectA>();
}
set;
}
'ObjectAList.set' must declare a body because it is not marked abstract, extern, or partial
Why is that?
You are trying to mix Auto implemented property with normal property. Moreover you need a backing field, otherwise you will run in to Stackoverflow exception. Your property declaration should be like:
private List<ObjectA> _ObjectAList; //private backing field
public List<ObjectA> ObjectAList
{
get
{
return _ObjectAList ?? new List<ObjectA>();
}
set
{
_ObjectAList = value;
}
}
Thats how the langauge works.
You cant do partial explicit / implicit.
Its all or nothing.
When you do it implicitly it just writes to an auto generated backing field, but it wants to do both sides.
Moreover your get is going to have a stack overflow even if the set worked because you are going to call the get over and over with no base case to end the recursion.
Consider the class:
public class foo
{
public object newObject
{
get
{
return new object();
}
}
}
According to MSDN:
Properties are members that provide a flexible mechanism to read,
write, or compute the values of private fields. Properties can be used
as though they are public data members, but they are actually special
methods called accessors. This enables data to be accessed easily
And:
Properties enable a class to expose a public way of getting and
setting values, while hiding implementation or verification code.
A get property accessor is used to return the property value, and a
set accessor is used to assign a new value. These accessors can have
different access levels. For more information, see Accessor
Accessibility.
The value keyword is used to define the value being assigned by the
set indexer.
Properties that do not implement a set method are read only.
while still providing the safety and flexibility of methods.
Does this therefore mean that at some point in time the value of the newObject property has a reference to the returned new object?
edit removed readonly from property
edit2 also would like to clarify that this is not the best use for a property but its done to try and illustrate the question more effectively.
You return a new object on each access to the property and that is not the expected behavior of properties. Instead you should return the same value each time (e.g. a value stored in a field). A property getter is simply glorified syntax for a method that returns a value. Your code compiles into something like this (the compiler creates a getter by prefixing the property name with get_ which is then emitted as IL):
public class foo
{
public object get_newObject()
{
return new object();
}
}
Each call to the getter will create a new object that foo doesn't know about or has access to.
Does this therefore mean that at some point in time the value of the newObject property has a reference to the returned new object?
No.
Property using a backing field:
class Foo {
readonly Object bar = new Object();
public Object Bar { get { return this.bar; } }
}
Using automatic properties:
class Foo {
public Foo() {
Bar = new Object();
}
public Object Bar { get; private set; }
}
A property is accessed using the same easy syntax as a public field. However, by using a property you can add code to the getter and the setter allowing you to do stuff like lazy loading in the getter or validation in the setter (and much more).
Under the hood, your property will simply be calling a function named get_newObject() that looks like this:
public object get_newObject()
{
return new object();
}
Since that is the case, it will always return a new object every time it is invoked.
If you want to retain a reference to the object, then I would recommend creating a private field to hold the data and having the property access that field, like so:
private object myObject;
public object newObject
{
if(myObject == null)
{
myObject = new object();
}
return myObject;
}
Since your property doesn't define set, and your field is private, newObject is basically eradonly outside of the containing class.
Properties in C# are "syntactic sugar". The code within the get block of a property is in fact put into a hidden get_PropertyName() method, and the set block into a hidden set_PropertyName() method. In the case of your code, the following method will be created:
public object get_newObject()
{
return new object();
}
You can see these hidden methods if you view the compiled assembly using Reflector, or ildasm.
When the property is used, the C# compiler converts any "get" accesses of your property into calls of the get_newObject() method. As an example:
If you were to write the following:
var foo = new foo();
var aNewObject = foo.newObject;
The compiler would convert that to:
var foo = new foo();
var aNewObject = foo.get_newObject();
So, in answer to your other question, the newly created object returned when someone "gets" the property won't be stored within your foo instance, the caller will simply get a new object every time.
Not exactly. Properties are just syntactic sugar so that you don't have to write accessor methods (like Java).
So this:
private int _myInteger;
public int MyInteger
{
get { return _myInteger; }
set { _myInteger = value; }
}
is equivilant to this:
private int _myInteger;
public int GetMyInteger()
{
return _myInteger;
}
public void SetMyInteger(int value)
{
_myInteger = value;
}
and it gets better with this, which is also equivilant:
public int MyInteger { get; set; }
How do I constrain property setter on Linq-To-Sql class
I have a custom field that needs validation and the designer class can be over written.
I have overrider setter methods which would work but how to I restrict setting on the Linq-To-Sql class?
public partial class Frequency : INotifyPropertyChanging, INotifyPropertyChanged
{
public void SetStartTime(TimeSpan startTime)
{
if(startTime.Days > 0){throw new Exception("No day value is valid for start time value";}
this._StartTime = string.Format("{0}:hh\\:mm\\:ss", startTime);
}
public TimeSpan GetStartTime()
{
IEnumerable<int> startTime = this._StartTime.Split(':').Cast<int>();
return new TimeSpan(startTime.ElementAt<int>(0), startTime.ElementAt<int>(1), startTime.ElementAt<int>(2));
}
}
LINQ 2 SQL has everything you need to overcome this problem if you use the LINQ to SQL Classes designer.
Let's say your table has a column "Number" of type Int32.
The designer will create:
Field -> _Number
Property -> Number
Method -> OnNumberChanging(int value)
Method -> OnNumberChanged()
The last 2 methods are partial. This means you don't have to touch the designer generated files in case you refresh your classes from the database.
By creating the following in another file:
public partial class MyLinqToSqlClass
{
partial void OnNumberChanging(int value)
{
//your code here
//throw exception if necessary when validating
}
}
you get what you need.
This piece of code gets called inside the set method of the Number property right before the value of the field gets changed.
This way you don't worry about using the set method of the property.
Hope this helps.