I'm quite sure this is a stupid question, but all my tries failed.
I have a custom control in which I'd like to have a complex property exposing many properties. I want to do this because I would have an expandable property in visual property manager, so I can set sub-properties easily because grouped together in parent property.
This is a schema of what I've done:
public partial class QViewer : UserControl
{
private Shortcuts toolsShortcuts = new Shortcuts();
private TestProp testProp = new TestProp();
public Shortcuts ToolsShortcuts { get { return toolsShortcuts; } }
public TestProp Test { get { return testProp; } }
}
public struct TestProp
{
public bool DoIt;
public DateTime Date;
}
public class Shortcuts
{
Keys toolArrow = Keys.None;
public Keys Arrow
{
get { return toolArrow; }
set { ... }
}
}
}
When I insert my custom control in a form (using another project inside same solution) and I open properties, both Shortcuts and Test are grayed, not expandable, so I can't set properties inside them.
What's wrong? Is there a better way to group properties than creating a class or a struct?
Thanks to everybody!
IIRC you need to write a TypeConverter to get the properties window to expand these properties.
Let's assume you use the following type for a complex property:
[DescriptionAttribute("Expand to see the spelling options for the application.")]
public class SpellingOptions
{
private bool spellCheckWhileTyping = true;
private bool spellCheckCAPS = false;
private bool suggestCorrections = true;
[DefaultValueAttribute(true)]
public bool SpellCheckWhileTyping
{
get { return spellCheckWhileTyping; }
set { spellCheckWhileTyping = value; }
}
[DefaultValueAttribute(false)]
public bool SpellCheckCAPS
{
get { return spellCheckCAPS; }
set { spellCheckCAPS = value; }
}
[DefaultValueAttribute(true)]
public bool SuggestCorrections
{
get { return suggestCorrections; }
set { suggestCorrections = value; }
}
}
Your properties probably look like this at the moment:
Notice that the Spell Check Options property is grayed out.
You need to create a TypeConverter to convert your object type so it can be displayed correctly. The .NET framework provides the ExpandableObjectConverter class to make this easier.
For example:
public class SpellingOptionsConverter:ExpandableObjectConverter
{
//...
}
You need to follow these steps to create a custom TypeConverter.
To implement a simple type converter that can translate a string to a Point
Define a class that derives from ExpandableObjectConverter (or TypeConverter).
Override the CanConvertFrom method that specifies which type the converter can convert from. This method is overloaded.
Override the ConvertFrom method that implements the conversion. This method is overloaded.
Override the CanConvertTo method that specifies which type the converter can convert to. It is not necessary to override this method for conversion to a string type. This method is overloaded.
Override the ConvertTo method that implements the conversion. This method is overloaded.
Override the IsValid method that performs validation. This method is overloaded.
Take a look at the following MSDN page for more information on how to implement a TypeConverter:
How to: Implement a Type Converter
After you've created the TypeConverter you can apply it to your custom type.
[TypeConverterAttribute(typeof(SpellingOptionsConverter)),
DescriptionAttribute("Expand to see the spelling options for the application.")]
public class SpellingOptions{ ... }
And all will be well:
I quickly summarized an elobarate example from MSDN. You can find an entire walkthrough here:
Getting the Most Out of the .NET Framework PropertyGrid Control
Related
I'm switching from Objective-C to C# to start using the Unity engine. So I'm trying to soak in all the C# differences. Obj-C has the #synthesize that auto creates the getters and setters. To to be honest they're sort of new to me. In Obj-C I'd often do:
#synthesize myProperty = _myProperty;
Then use the _myProperty in the local class code and access that property outside of this class using myProperty. Or more accurately classInstance.myProperty.
Also in Obj-C you can declare a property to be readonly and not worry about accidentally changing it's value outside the class.
In C# I'm trying to write proper object oriented code and I struggle with this. I'm a C coder at heart and am comfortable having access to everything everywhere, which I know is bad and unnecessary. I also don't want to expose tons of properties to the GameObject Inspector. I prefer to do as much programmatically as possible.
So what is the best way to declare properties so I can access them from another class but also so they are not exposed in the Inspector? Here are some possibilities that I've encountered and used:
// 1. public static - public without being exposed in inspector
public static int myProperty;
// 2. the public _text doesn't appear in the inspector but the text one does.
public string _text;
public string text {
get { return _text; }
set {
_text = value;
}
}
// 3. private _underscore version with no setter - does removing the set make it read only?
private float _current;
public float current {
get { return _current; }
}
// 4. creating my own getter function
private int myValue;
...
int GetMyValue() {
return myValue;
}
Also.. I read somewhere that in .NET you shouldn't use underscores in property names. I don't really know what the underscore version of the property does or represents. I thought in Obj-C it effected the scope, but don't really know.
Am I even correct in calling variables properties?
Someone suggested prop tab tab which produces this:
public object MyProperty {
get;
set;
}
Unfortunately that doesn't really answer my question about read only. Is an int or string even an object? It's not in Obj-C.
Public variables (not fields) are shown in the Unity inspector. If you want a public variable to be hidden, you can preface it with NonSerialized, like this:
[System.NonSerialized]
public bool m_HideWhenInactive = false;
You can also avoid this problem entirely by making it a property. No properties are shown in the inspector:
public bool m_HideWhenInactive { get; set; }
As a fun bonus (not your question, I know), you can have a property that's world-read, private-write:
public bool m_HideWhenInactive { get; private set; }
And finally, if you DO want a variable to be serialized and stored in a prefab, but you don't want the designers editing it (if you intend to write a custom editor class), there's a different annotation for that:
[HideInInspector]
public bool m_HideWhenInactive = false;
Static fields are never shown in the inspector.
The NonSerialized and HideInspector attributes are the two options you must consider to hide members of the class from the Unity inspector. NonSerialized is not specific to Unity, HideInspector is specific to Unity. Unity looks for both of these attribute in your compiled code to determine what gets exposed in the inspector.
If you want a publicly read only property you declare it like so...
[System.NonSerialized]
private string _text;
/// <summary>
/// Gets the Text
/// </summary>
/// <remarks>May be set within this class or derived classes</remarks>
public string Text {
get { return _text; }
protected set {
_text = value;
}
}
You seem to be having issues with the meaning of access modifiers...
See this page...
https://msdn.microsoft.com/en-us/library/wxh6fsc7.aspx
Briefly...
public = accessible from anywhere, do not declare backing variables on properties as public, otherwise people can simply skip your property accessor.
protected = accessible within your class and from classes inheriting the class
internal = accessible within the same assembly
protected internal = accessible within the same assembly and from
classes inheriting the class
private = accessible only within your class
You can do away with backing variables simply by declaring
/// <summary>
/// Gets or sets the Text
/// </summary>
public string Text { get; set; }
/// <summary>
/// Gets the current
/// </summary>
public float Current { get; protected set; }
Since the advent of auto-implemented variables, there are no technical reasons for creating properties with backing variables unless you have additional logic you would like executed on the get and/or set.
e.g you wanted to create Observable entities that raise an event when a property is changed...
private int _id;
public int ID
{
get
{
return _id;
}
set
{
if (_id != value)
{
OnIDChanging(value);
ReportPropertyChanging("ID");
_id = StructuralObject.SetValidValue(value);
ReportPropertyChanged("ID");
OnIDChanged();
}
}
}
In terms of coding standards, there are plenty of them on the net. I'd recommend IDesign's...
http://www.idesign.net/downloads/getdownload/1985
You'll notice I changed the casing on the code you posted, the casing I've used adhere's to IDesign's naming guidelines
The correct way to create properties really depends on what it is you're trying to accomplish. If you're only wanting to have a property be created for further use you can create the shorthand way:
public object MyProperty { get; set; }
If more functionality is required, you can add additional functionality, such as:
private int _myInt;
public int MyInt {
get { return this._name; }
set {
if (this._name == 1) {
this._name = value;
} else {
this._name = 0;
}
}
}
The answer of your question is it simply depends on what it is you're looking to achieve and both ways are accepted.
The use of getter and setter methods, such as those found in Java, are frowned upon in C#.
To answer your other question, String is an object in C#. int is a primitive type.
Here's a quick summary of your problems.
There is a so called snippet in C# that allows you to quickly generate code. The quick shortcut for it is typing prop and then pressing tab which would generate a code to something like this.
public int MyProperty { get; set; }
Now if you're going to create fields, and you dont want to expose that to an instance. You should make it private.
Example
private int myVar; // private is not exposed on instances only public properties are
public int MyProperty
{
get { return myVar; }
set { myVar = value; }
}
Now for static fields, static fields/properties are type accessible. So to hide them, you only have to make them private
Example
private static bool myProp; // can't be accessed on the Program Type
public static bool MyProp { get; set; } // can be accessed on the Program Type
class MyClass
{
public MyClass()
{
Program.MyProp = true;
Program.myProp= true; // wont build
}
}
If you want it to be readonly and prevent modification, you can do it like this.
public int MyProperty { get; private set; } // can get but not set
private int myVar;
public int MyProperty
{
get { return myVar; } // same as the top but with a field
}
For a deeper and better understanding, please do read about What are Access Modifiers in C#?
Property patterns in the context of the Unity engine tend to differ slightly to the 'norm' of C# because of you are often interested in making them tweakable data in the editor. This means serialization.
Unity cannot serialize properties
Unity can serialize fields of primitive types and types inheriting from UnityEngine.Object are serialized references
Unity can serialize list and arrays of the types mentioned above as well
Serialized fields on MonoBehaviours are exposed in the editor and are editable
public fields are serialized by default and private fields if they are marked with the [SerializeField] attribute.
Unity also serializes fields on classes marked with [System.Serializable] if the class is a field on a MonoBehavior
For a more in-depth discussion see: https://blogs.unity3d.com/2014/06/24/serialization-in-unity/
The following pattern is common, the backing field can be set by the developer, without needing to recompile, and cannot be changed by external code at run-time.
[SerializeField]
private int editableInEditor;
public int NotEditableInEditor
{
get { return editableInEditor; }
}
So is this pattern, a lazy-getter.
private DerivedMonoBehaviour component;
public DerivedMonoBehaviour Component
{
get
{
if(component == null)
{
// Note: Using the null-coalescing operator ??
// is inadvisable when dealing with UnityEngine.Object
// references.
// See: https://blogs.unity3d.com/2014/05/16/custom-operator-should-we-keep-it/
component = GetComponent<DerivedMonoBehaviour>();
}
return component;
}
}
This question already has answers here:
Implementing INotifyPropertyChanged - does a better way exist?
(35 answers)
Closed 9 years ago.
In ViewModels there are typically lots of these
private string someField;
public string SomeField
{
get
{
return someField;
}
set
{
someField = value;
NotifyOfPropertyChanged(() => SomeField);
}
}
Is there any way to get a short version of such a construct, that is even Bindable?
So that you only have to write something like:
public Bindable<string> SomeField;
perhaps with an action that shall be fired for NotifyPropertyChanged...
I suppose you could create your own class that maintains a value and raises INotifyPropertyChanged against the containing class that you could create like:
public Bindable<string> SomeField = new Bindable<string>("test", this);
And then Binding against SomeField would access the contained value and setting it would lead to INotifyPropertyChanged being raised against this
You'd need to use some implicit cast operators in order to get the binding system to see your Bindable<T> as a source of T and a place to put T
See: http://msdn.microsoft.com/en-us/library/85w54y0a.aspx
Something along the lines of the following may suffice:
public class Bindable<T>
{
private T _value;
private PropertyChangedEventHandler _notifyHandler;
private INotifyPropertyChanged _notifyTarget;
private string _name;
public Bindable(PropertyChangedEventHandler notifyHandler, INotifyPropertyChanged notifyTarget, string name, T value = default(T), bool trigger = false)
{
_value = value;
_name = name;
_notifyHandler = notifyHandler;
_notifyTarget = notifyTarget;
if (trigger)
{
_notifyHandler(_notifyTarget, new PropertyChangedEventArgs(_name));
}
}
public implicit operator T(Bindable<T> bindable)
{
return bindable._value;
}
public implicit operator Bindable<T>(T value)
{
return new Bindable<T>(_notifyHandler, _notifyTarget, _name, value, true);
}
}
The above code is crude and a better version could no doubt be created, but it should point you in the direction you need to go.
On further investigation of my proposed solution I've found that it would be problematic to get to work owing to the implicit cast from T to Bindable<T> in order to remember the target and other details, I'm sure this sort of solution contains enough ideas to lead to a working one.
There exist auto properties, that can be used as a shortcut for properties without logic.
The two following properties are equivalent:
private string someField;
public string SomeField
{
get { return someField; }
set { someField = value; }
}
public string SomeField { get; set; }
However, there is no built-in way to introduce a change notification into this.
But if you want to invest time and/or money, there are ways to make auto properties notify about changes:
Use an AOP framework like PostSharp. It will inject this functionality in a post-compile step: http://www.postsharp.net/model/inotifypropertychanged. The disadvantage of this approach is that PostSharp isn't free.
Use dynamically created proxy classes. At runtime, you can create a class that derives from your actual ViewModel and overrides each property with change notification. The disadvantage of this approach is that you would need to use that proxy instead of your class and that all your properties would need to be virtual.
We are doing alot of INotifyPropertyChanged implementation in our View Models and quite frankly are getting tired of having to fire the property changed events explicitly in our code for both inconvenience and aesthetic reasons.
I want to put an extension on the setter of our property, making the resulting code look like:
public string LazyAccessor
{
get;
set.notify();
}
Is there a way to do this? Can we invent one if there isn't?
Check out NotifyPropertyWeaver. This will modify your code during the build process to have your properties implement the INotifyPropertyChanged pattern.
This is available as a Visual Studio Extension
Aspect oriented programming could be solution of your problem.
See Aspect Oriented Programming in C#.
And some examples here: http://www.codeproject.com/Articles/337564/Aspect-Oriented-Programming-Using-Csharp-and-PostS
Your "set.notify()" could work with some Reflection, but I donĀ“t think this would be good solution and you will still need to implement getter and setter.
Extension methods can only be added to types. The getters and setters on automatic properties are converted into methods with backing variables by the compiler, so there is no way to put an extension method on them.
Is there a way to do this?
No, there isn't, not like you posted. Extension methods operate on types, not getters or setters.
Can we invent one if there isn't?
That would require changes to the C# specification - not a likely thing to happen.
There are other approaches that you can take to ease this - using a base class with a method that will make the boiler plate calls for you for example.
They didn't make it into 4.0, but are rumored to be included in 5.0.
I found this approach helpful.
You couldn't do it on the set itself. That is an action. You might however be able to do this:
public static class extensions()
{
public static NotifyAccessorSet(this string value) { some code }
}
public class SomeClass()
{
.....
private string mAccessor;
public string LazyAccessor{
get { return mAccessor; }
set { mAccessor = value; mAccessor.NotifyAccessorSet(); }
}
}
It's somewhat off the top of my head and keep in mind that the extension method would apply to all types string so you might want to implement your own return type and apply the extension method to it. Return that type then from lazyaccessor.
you can emulate a 'property-like' behavior without calling the event manualy by overriding the conversion operators of a custom generic struct.
The following is my solution:
public struct column<TType>
{
private TType _value;
private column(TType value) : this()
{
_value = value;
}
private void Set(TType value)
{
// Implement your custom set-behavior...
}
private TType Get()
{
// Implement your custom get-behavior...
return _value;
}
public override string ToString()
{
return _value.ToString();
}
public static implicit operator column<TType>(TType p)
{
column<TType> column = new column<TType>(p);
column.Set(p);
return column;
}
public static implicit operator TType(column<TType> p)
{
return p.Get();
}
}
I declare the struct with a generic parameter to avoid from conversion errors. You can use it like this:
public class Test
{
public column<int> kKey;
public column<float> dMoney;
public column<string> cValue;
public Test()
{
kKey = 42;
dMoney = 3.1415926f;
cValue = "May the force be with you!";
}
}
...I know, the question is outdated but it may help someone in the future.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Can I create an automatic property (no private member) with get and set code?
Access automatic property - c#
I've worked with explicit getters / setters such as
private bool myField;
public bool MyField
{ get { return myField; }
set { myField = value; }
}
Now, working with C# .net 4.0, you have the ability to abbreviate such as
public bool MyField
{ get; set; }
Now, if I want to override only the SET portion, what is the INTERNAL reference I should be referencing... in the first sample, I know I am explicitly referring to the private of "myField", but with the second version, what am I referencing? Does the compiler just throw an implied "_" such as _MyField as the private side of the element?
class Parent
{
public virtual bool MyField { get; set; }
}
class Child : Parent
{
public override bool MyField
{
//ommitting get portion
set
{
//other custom code goes here
base.MyField = value;
}
}
}
Here a class inherits from a class with a property an overrides only the setter. Alternatively you could override the getter and just leave it as return base.MyField to not change the functionality.
Edit:
The issue was raised that when doing this the half that was left out (the get in my example) wouldn't exist in the child class, making the property read/write only. That is not the case, the half that is left out simply inherits its functionality from its parent. See the following addition to my example to demonstrate.
Child c = new Child();
c.MyField = true;
if (c.MyField)
{
Console.WriteLine("hi");
}
(This will indeed print "hi", no errors compile or runtime.)
whatever the compiler does in this case is an implementation detail which can change in the future without further notice!
Thus I strongly recommend to not make your code depend on such an implementation detail and just use the first option (override both accessors and have field to explicitely back the property) in this case...
You would access the property in the same way, using MyField. However, if you did not want code outside the class to be able to set the property, you can use:
public bool MyField { get; private set; }
I have a type SearchBag that holds a bunch of strings and nullable integers to use for passing on search values. I need a way to check if the search bag contains any values.
I'm currently trying to do it like this:
public bool HasValues()
{
return GetType().GetProperties().Any(p => p.GetValue(this, null) != null);
}
But was wondering if there's a better way.
Without modifying the SearchBag type, there isn't a better way.
EDIT: You could change the type to set a boolean flag in every property setter, then check the flag instead of using Reflection.
You could use Post Sharp to intercept the request to change a property value. You could have all search classes inherit from a common class with a List<string>. Then create an aspect attribute to add a property name to that dictionary whenever the value changes. The following is just a sample, and has bugs:
[Serializable]
public class PropertyChangeAwareAttribute : OnMethodBoundaryAspect
{
public override void OnEntry(MethodExecutionEventArgs eventArgs)
{
if (eventArgs.Method.Name.StartsWith("set_"))
((SearchBagBase)eventArgs.Instance).PropertiesChanged.Add(eventArgs.Method.Name);
base.OnEntry(eventArgs);
}
}
abstract class SearchBagBase
{
public List<string> PropertiesChanged = new List<String>();
}
[PropertyChangeAware]
class RegularSearch : SearchBagBase
{
public String Key { get; set; }
}
with usage:
RegularSearch regularSearch = new RegularSearch();
regularSearch.Key = "toys";
regularSearch.PropertiesChanged.ForEach(Console.WriteLine);