C# How to pass Properties in a generic way without Reflections? - c#

Currently I have three properties in class MyClassOne. The number of properties may increase in future. Whenever any of the property changes, I need to call a method called SavePropertyToFile() which is responsible to set the corresponding property (AnotherPropertyOne, AnotherPropertyTwo or AnotherPropertyThree) of another class.
My sample code (which is of course not working) is below:
Class MyClassOne
{
public bool PropertyOne
{
get => _propertyOne;
set
{
if (_propertyOne == value)
return;
_propertyOne = value;
SavePropertyToFile(value, MyAnotherClass.AnotherPropertyOne); //<------------------
NotifyOfPropertyChange(() => _propertyOne);
}
}
public bool PropertyTwo
{
get => _propertyTwo;
set
{
if (_propertyTwo == value)
return;
_propertyTwo = value;
SavePropertyToFile(value, MyAnotherClass.AnotherPropertyTwo); //<------------------
NotifyOfPropertyChange(() => _propertyTwo);
}
}
public bool PropertyThree
{
get => _propertyThree;
set
{
if (_propertyThree == value)
return;
_propertyThree = value;
SavePropertyToFile(value, MyAnotherClass.AnotherPropertyThree); //<------------------
NotifyOfPropertyChange(() => _propertyThree);
}
}
SavePropertyToFile(bool value, TProperty myPropertyOfAnotherClass)
{
myPropertyOfAnotherClass = value;
// Some more lines of Code
RefreshProgram();
}
}
In the code above, I need to find a way so that I can parse the correct property of AnotherClass. I already had a look at this another SO question, but I am not able to apply any of the answer for my case.
How can I parse different properties to a method?
Update: As per the suggestions in the comments, I have tried to use "Nathan Baulch" answer's option-2 but then I getting warning/error wiggly line as shown in the screenshot below:

If the idea is to make several classes use the same property, my approach is to wrap the values in a class:
public class Changeable<T> : INotifyPropertyChanged
{
private T currentValue;
public Changeable(T initialValue) => currentValue = initialValue;
public T Value
{
get => currentValue;
set
{
if (!EqualityComparer<T>.Default.Equals(currentValue, value))
{
this.currentValue = value;
Changed?.Invoke(this, value);
OnPropertyChanged(nameof(Value));
}
}
}
public event EventHandler<T> Changed;
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
You can then just let both classes use the same actual object. This approach can also be used to cut down on boilerplate for wpf, instead of declaring getters and setters you can just write:
public Changeable<bool> MyProperty {get;} => new (false);
Just remember to update the binding: {Binding MyProperty.Value}
You can also write various extensions. For example if you want to update one property whenever some other property updates:
MyProperty.BindTo(MyIntProperty, intValue => intValue > 0);
So whenever MyIntProperty changes sign, the MyProperty would be updated and raise its changed event. I'm not going to include all the code behind this, since it is fairly large, but I hope you get the idea. This approach makes it possible to link various UI values in a convenient way, but it can also make the code more difficult to understand and debug, so some caution is advised.

Related

Don't Understand How INotifyPropertyChanged function

INotifyPropertyChanged interface implementation (appropriate event) and helper method works fine in my code but I really don't understand how it works. My book does a poor job of explaining it to me in my opinion or I am not very smart.
We have a separate class Car.cs added to my solution with the following code (example from the book) and it should work in TwoWay Binding regards to TextBox control in my WPF application being changed when object's instance is being changed too:
public class Car: INotifyPropertyChanged
{
private string _make;
private string _model;
public event PropertyChangedEventHandler PropertyChanged;
public Car()
{
}
public string Make
{
get { return _make; }
set
{
if (_make != value)
{
_make = value;
OnPropertyChanged("Make");
}
}
}
public string Model
{
get { return _model; }
set
{
if(_model != value)
{
_model = value;
OnPropertyChanged("Model");
}
}
}
private void OnPropertyChanged (string propertyName)
{
if (PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}}
And here is the code which I made myself after learning Microsoft learning materials and it looks and works better imo:
public class Car: INotifyPropertyChanged
{
private string _make;
private string _model;
public event PropertyChangedEventHandler PropertyChanged;
public Car()
{
}
public string Make
{
get { return _make; }
set
{
_make = value;
OnPropertyChanged();
}
}
public string Model
{
get { return _model; }
set
{
_model = value;
OnPropertyChanged();
}
}
private void OnPropertyChanged ()
{
if (PropertyChanged != null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(""));
}
} }
So I have the foolowing question regards to example from the book (the first one):
What this part means? What's the point to check if property not equals to value (never saw anything like it before when during the Set part of the property you check that field of the class checked for being not equalled to value)? Code works even without it. No explanation for it in the book. Here is the code under question:
set
{
if (_make != value)
{
_make = value;
OnPropertyChanged("Make");
}
Why if you'll write the name of the property without brackets in the above-mentioned small piece of code (in subparagraph one) then it will not work? I meant if you'll write Make then it does not work and you should write "Make".
Thanks in advance!
Here is a basic example of how to correctly implement the IPropertyChanged interface, which notifies the view to re-draw on property changing its value.
public class PropertyChangedEventStackOverflow : INotifyPropertyChanged
{
//We have a private property of the same public property. This allows us to store the privous value of the property which we can
//get at any time when we ask.
string name = string.Empty;
//Public property is required to do two-way-binding or one-way-binding from model to the view.
public string Name
{
get => name;
set
{
if (name == value) //Check if the private property is already equals to the exact same value to avoid extra memory
return; //and uneccasary screen re-drawing. So we just return and avoid calling the OnPropertyChanged.
name = value; //If the value is different meaning we want to notify view and tell it to re-draw the screen for us.
OnPropertyChanged(nameof(Name));
}
}
//We create this helper metod to avoid doing something like this every single time we want to notify
string surname = string.Empty;
public string Surname
{
get => surname;
set
{
if (surname == value)
return;
surname = value;
PropertyChanged(this, new PropertyChangedEventArgs(nameof(Surname)));
}
}
//Here is the method to create for OnPropertyChangedEvent
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
var changed = PropertyChanged;
if (changed == null)
return;
changed.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
If you want to go step further and want to have an Action when your property has changed you can do something like this. backingStore type T = private property
public bool SetProperty<T>(ref T backingStore, T value,
[CallerMemberName] string propertyName = "",
Action onChanged = null)
{
if (EqualityComparer<T>.Default.Equals(backingStore, value))
return false;
backingStore = value;
onChanged?.Invoke();
OnPropertyChanged(propertyName);
return true;
}
You can give it an action to execute if once a property has changed.
Because raising the PropertyChanged event can be expensive in terms of performance (for example when a complex view has to redraw itself in order to display the latest data), it's a recommended pattern to raise it only when necessary.
It's only necessary when the new value has changed. To update the binding when the new value and the old value are the same is redundant and potentially expensive.
The following example is a very verbose version to highlight what's going on:
private string myProperty;
public string MyProperty
{
get => this.myProperty;
set
{
string newValue = value;
string oldValue = this.MyProperty;
if (newValue != oldValue)
{
this.myProperty = newValue;
OnPropertyChanged(nameof(this.MyProperty));
}
}
}
For reasons of performance, passing an empty string (string.Empty or "") or null to the PropertyChangedEventArgs instance, instead of the property name, will instruct the binding engine to update all bindings of the class that raises the PropertyChanged event.
In other words, it's like raising the PropertyChanged event for all properties at once.
That's why you only do this when this behavior is explicitly desired (for example when you reset and clear all properties):
/* Will raise the PropertyChanged event for ALL properties defined by the declaring type */
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(""));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(string.Empty));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(null));
/* Will raise the PropertyChanged event ONLY for the particular property that matches the provided property name */
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("MyProperty"));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.MyProperty)));
"Make" is called a string literal. Every literal enclosed in double-quotes is interpreted as plain text by the compiler (string literal). If it wasn't the double-quotes, the compiler expects the value to be a language object (for example a variable or type).
If you check the signature of the constructor of PropertyChangedEventArgs you will see that it expects the property name as string.
Using Make (without the double-quotes) is a simple value reference (local or member variable) that returns the value of the Make property and not the name of the property (member name).
The property name is required to tell the binding engine which property has changed and therefore which Binding needs to be updated.
The following example assumes that the property Make is set to a value of "BMW":
public string Make
{
get => this.make;
set
{
// For example 'value' is "BMW"
this.make = value;
// Invocation a)
// Pass the property name as argument.
OnPropertyChanged("Make"); // Same as: OnPropertyChanged(nameof(this.Make))
// Invocation b)
// Pass the property value as argument
OnPropertyChanged(Make);
// Verbose version of b)
string modelMake = Make;
OnPropertyChanged(modelMake);
}
}
Version b) won't work, because the binding engine needs the property's member name and not the property value.
See Microsoft Docs: Strings and string literals to learn about strings.
See INotifyPropertyChanged to learn the recommended pattern to implement the interface
Remarks
Checking variable (for example an event delegate) for null using an if statement and the Null-conditional operator ?. or ?[] is redundant.
In high performance code you would want to avoid the redundant double checking.
The following versions are the same:
private void OnPropertyChanged()
{
if (PropertyChanged != null)
{
PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
private void OnPropertyChanged()
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
private void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
What's the point to check if property not equals to value
it is just to avoid unnecessary updates. It is not strictly required. Whenever you have events to signal that something is updated it is often a good idea to check if the thing actually changed, since you do not know what is listening to the event, it could potentially trigger some slow computations.
Why if you'll write the name of the property without brackets in the above-mentioned small piece of code (in subparagraph one) then it will not work?
Because the event needs a string. You can let the compiler insert this string for you by writing OnPropertyChanged(nameof(Make)); You can also use CallerMemberName attribute to let the compiler insert this automatically, just call OnPropertyChanged() within your property.
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
Going one step further you you can create a method that does both the comparison, field update, and event, letting you write a one line setter => Set(ref _make, value);
private void Set<T>(ref T field, T value, [CallerMemberName] string caller = "")
{
if (!EqualityComparer<T>.Default.Equals(field, value))
{
field = value;
OnPropertyChanged(caller);
}
}
However, my preference tend to be to wrap all of this inside a separate class:
public class Changeable<T> : INotifyPropertyChanged
{
private T currentValue;
public Changeable(T initialValue) => currentValue = initialValue;
public T Value
{
get => currentValue;
set
{
if (!EqualityComparer<T>.Default.Equals(currentValue, value))
{
this.currentValue = value;
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
That way you can declare a property like public Changeable<string> Make {get;} = new (""); and bind to it like {Binding Make.Value}
INotifyPropertyChanged is an interface which only requires a class to implement it's requirements. Which is basically "just" an Event.
public interface INotifyPropertyChanged
{
//
// Summary:
// Occurs when a property value changes.
event PropertyChangedEventHandler? PropertyChanged;
}
The Method OnPropertyChanged is just a "helper" to raise this event. But the important part here, is that the INotifyPropertyChanged implementation by itself is not doing anything.
However WinForms and WPF are automatically subscribing in some higher-hirachy classes to such Event. They identify such classes through reflection and add themself to one of the subscribers to the PropertyChanged Event - which your class still needs to raise.
For this purpose you need to override the Setters of your properties:
public string Examle
{
get { return _field; }
set
{
_field = value;
OnPropertyChanged(); // <---
}
}
Otherwise the subscriber will never be notified. However the whole purpose of this is to decouple the handling of changes from the "Model" so your class which act's as container to the data - since the container can be passed to different forms, which might want to handle this container different.
The check if the value actually changed is only something you CAN do - to prevent the notification of the subscriber (let's say your data grid) to re-run all validations you've setup for such property. To avoid unnecessary runs of such validations this if will prevent notifying subscribers of such changes where a value get's re-assigned, but it remains the same.
The auto-wiring of the subscriber however is abstraced for you as developer, which can create difficulties for beginners to understand - however makes your life much more easier on the long run, as you can rely on the Framework as such (less for you to implement, test, etc.) so it's just a "convention" to use INotifyPropertyChange Interface, but the basic building blocks are general C# constructs.
Hope this helped a little :)

Is there a way set a dirty flag in a Xamarin ViewModel after the properties are initialized?

I want to set a dirty flag for any of the required properties in my view model. I initialize IsDirty to false in the constructor. Unfortunately all of the setters in my properties are called after the constructor. Is there a way I can set IsDirty to false after all of the setters? The setters all have a line IsDirty=true;
I'm using the Prism framework with Xamarin 4.0, but Prism documentation doesn't have anything on the ViewModel life cycle.
My redacted constructor looks like this:
public SomeDetailsViewModel(INavigationService navigationService) : base(navigationService)
{
Sample = new SampleDTO();
InitializeLookupValues();
_samplesService = new SampleService(BaseUrl);
TextChangedCommand = new Command(() => OnTextChanged());
AddSampleCommand = new Command(() => AddCurrentSample());
CancelCommand = new Command(() => Cancel());
IsDirty = false;
}
Edit 3:
The constructor calls InitializeLookupValues(). These appear to be the culprit.
private async Task InitializeLookupValues()
{
App app = Prism.PrismApplicationBase.Current as App;
string baseUrl = app.Properties["ApiBaseAddress"] as string;
_lookupService = new LookupDataService(baseUrl);
int TbId = app.CurrentProtocol.TbId;
int accessionId = CollectionModel.Instance.Accession.AccessionId;
Parts = await _lookupService.GetParts(accessionId);//HACK
Containers = await _lookupService.GetSampleContainers(TbId);
Additives = await _lookupService.GetAdditives(TbId);
UnitsOfMeasure = await _lookupService.GetUnitsOfMeasure();
// with a few more awaits not included.
}
After exiting the constructor each of the properties are set. They look like this one.
public ObservableCollection<PartDTO> Parts
{
get
{
return parts;
}
set
{
SetProperty(ref parts, value);
}
}
private PartDTO part;
public PartDTO SelectedPart
{
get
{
return part;
}
set
{
SetProperty(ref part, value);
IsDirty = true;
}
}
Where IsDirty is defined thus:
private bool isDirty;
public bool IsDirty
{
get
{
return isDirty;
}
set
{
SetProperty(ref isDirty, value);
Sample.DirtyFlag = value;
}
}
I haven't explicitly set any of the properties. I would like to avoid their being initialized automatically, or call something after them.
Edit
Just a note to everyone I have been debugging to find out what I could. I found that in each data-bound property the getter is called twice, then the setter is called. I looked at what generated code I could find, and there is no obvious place where data binding is explicitly calling the setter.
Edit 2
What I hadn't shown before, and now looks likes it's a critical piece of information, was that I populate the ObservableCollection with an async call to a service. As far as I can tell, because of XAML data binding, the SelectedPart property setter is called. If I debug slowly this start to show in some places. I've added the async call above.
Is there a way I can set IsDirty to false after all of the setters?
The setters aren't called by themselves, there has to be someone calling them. You should identify who's doing that and either stop him from setting stuff without good reason (preferred) or make him reset the dirty flag after he's done.
As suggested in the comments, adding a breakpoint in the setter and having a look at the stacktrace is a good starting point for finding the source of the setting... if I had to guess, I'd suspect some navigation related callback.
But you should try to make sure that the view model is initialized after the constructor and that IsDirty actually means "has been changed through the view" and not "maybe changed by the user, might also be just part of a delayed initialization".
After your multiple edits, an edit from me:
You should modify your architecture to account for the asynchronous initialization of your view model. Just running everything in parallel and hoping for the best rarely works.
You could make the properties read-only until initialization is complete, for instance, and set IsDirty to false at the end of InitializeLookupValues.
Pseudo-Code:
Constructor()
{
Task.Run( async () => await InitializeAsync() );
}
string Property
{
get => _backingField;
set
{
if (_isInitialized && SetProperty( ref _backingField, value ))
_isDirty = true;
}
}
private async Task InitializeAsync()
{
await SomeAsynchronousStuff();
_isInitialized = true;
}
private bool _isInitialized;
private bool _isDirty;
Probably, you want to expose _isInitialized as a property to the view to show some hourglass, and use a ManualResetEvent instead of a simple bool... but you get the idea.
Since the SetProperty methods are overridable you can inject some custom logic. This could be very useful for when you have objects that you need to validate if they have been altered.
public class StatefulObject : Prism.Mvvm.BindableBase
{
private bool _isDirty;
public bool IsDirty
{
get => _isDirty;
private set => SetProperty(ref _isDirty, value);
}
protected override bool SetProperty<T>(ref T storage, T value, Action onChanged, [CallerMemberName] string propertyName = null)
{
var isDirty = base.SetProperty(ref storage, value, onChanged, propertyName);
if(isDirty && propertyName != nameof(isDirty))
{
IsDirty = true;
}
return isDirty;
}
public void Reset() => IsDirty = false;
}
Keep in mind that when you initialize fields in this IsDirty would be true, so before binding you would want to call the Reset method to set IsDirty back to false that way you can reliably know when a field has been changed.
Note that how you handle this is somewhat up to you. For instance you might do this with Linq...
var fooDTOs = someService.GetDTOs().Select(x => { x.Reset(); return x; });
You might also enforce a pattern like:
public class FooDTO : StatefulObject
{
public FooDTO(string prop1, string prop2)
{
// Set the properties...
Prop1 = prop1;
// Ensure IsDirty is false;
Reset();
}
}

Minimizing WPF boilerplate code on bound properties

Consider a WPF dialogue with lots of input fields, which are bound to properties in a view-model. E.g.
...
<TextBox Text="{Binding FirstName}">
...
public string FirstName {
get { return mFirstName; }
set {
if (mFirstName == value) return;
mFirstName = value;
OnPropertyChanged("FirstName");
}
}
As there are tens of fields like this, I would like to minimize the boilerplate C# code to be written. What options do I have?
If you have the option of using a base class, consider inheriting view model objects from something like this:
public abstract class BindableBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (Equals(storage, value))
{
return false;
}
storage = value;
// ReSharper disable once ExplicitCallerInfoArgument
OnPropertyChanged(propertyName);
return true;
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected void OnPropertiesChanged(params string[] propertyNames)
{
foreach (string propertyName in propertyNames)
{
// ReSharper disable once ExplicitCallerInfoArgument
OnPropertyChanged(propertyName);
}
}
}
Example usage, showing that the boilerplate is greatly reduced:
public sealed class ViewModel : BindableBase
{
private string name;
public string Name
{
get { return name; }
private set { SetProperty(ref name, value); }
}
}
(If you can't use a base class (e.g., you already have one or are using properties on framework elements), you still have the option of adding similar support directly in the class in question.)
I can make your code a little easier to transform into a snippet.
if (mFirstName != value) {
mFirstName = value;
OnPropertyChanged("FirstName");
}
If just the time taken to write it is a pain, and you're using WPF a lot, snippets may also be of use. I know in Sublime Text, VS Code, and Visual Studio, Snippets can be invaluable. Otherwise, I think it's as bare bones as you can get, unless there's something I am not seeing
I use Fody to inject property changed code at compile time. Your class gets an [ImplementPropertyChanged] attribute, then your { get; set; } properties become notifying properties in the compiled code.
https://github.com/Fody/PropertyChanged
First, as I guess you already use Microsoft.Prism, you can drop the string and profit from CallerMemberNameAttribute behind the scenes for you, so that your code would look like this:
public string FirstName {
get { return mFirstName; }
set {
if (mFirstName == value) return;
mFirstName = value;
OnPropertyChanged();
}
}
This is also equivalent to c# 6.0 nameof(FirstName) operator.
Second, you can dig into AOP and abstract the boilerplate to an attribute. One of the AOP frameworks that deals with this is PostSharp and using it your code could look like this:
[NotifyPropertyChanged]
public class Customer
{
public string FirstName { get; set; }
Though it's not free, and AOP has it's drawbacks (thanks Evk).
Similar questions have been asked 1,2, and there does not seem to be optimal answer right now sadly, as it's everyones pain.

Property Getters and Setters when implementing INotifyPropertyChanged?

I am trying to implement INotifyPropertyChanged for a lot of classes, and each of these classes have lots and lots of properties. I have been following this MSDN documentation for how to implement INofifyPropertyChanged, but their instructions don't seem to be practical in cases where a class has many many properties.
Currently most of my properties use the short hand:
public DateTime? DateClosed { get; set; }
But the documentation says that i need to add the following to each setter method:
// Call OnPropertyChanged whenever the property is updated
OnPropertyChanged("DateClosed");
This means that I then need to declare a body for the get method and declare private variables to handle the actual getting and setting of properties. Like this:
private DateTime? _dateOfIncident = null;
public DateTime? DateClosed
{
get { return _dateOfIncident; }
set
{
_dateOfIncident= value;
// Call OnPropertyChanged whenever the property is updated
OnPropertyChanged("DateClosed");
}
}
Does anyone know a way around this?
A few classes can easily be changed to implement INotifyPropertyChanged. But since you state you have a lot of classes with a lot of properties, it's a real burden to get this done manually or even with templates.
What you really need is a tool that does it for you, so I present you Fody and it's NotifyPropertyChanged plugin. What Fody does is weave some extra code in between your code at compile time. The only thing you have to do is add a single attribute on the classes you want to implement INotifyPropertyChanged and the rest is done for you.
[ImplementPropertyChanged]
public class Person
{
public string GivenNames { get; set; }
public string FamilyName { get; set; }
public string FullName
{
get
{
return string.Format("{0} {1}", GivenNames, FamilyName);
}
}
}
I'm not sure you're going to find a workaround here. Auto-properties, as you're using them now, are really just a compiler shorthand that get's converted to full properties with a backing field eventually anyway (at least, as I understand it).
The use of INPC is a routine that's sorta separate and apart from the duty of a normal property. It's notifying subscribers (usually, your view XAML) that the property in question has changed or is changing.
tl;dr -- you're not going to get around having to rewrite autoproperties to full properties with backing fields. But toolkits like MVVMLight have some great Visual Studio code snippets to make this relatively fast. Eventually you can even do this:
private string _someString;
public string SomeString
{
get { return _someString;}
set
{
//Set returns bool, so you can trigger other logic on it!
Set(() => SomeString, ref _someString, value);
}
}
This gives you some neat features:
Strong naming (unlike the magic string in your example)
Set only triggers INPC event if the value is different
Set returns boolean so you can perform more action if the value changed
MVVMLight is nice in that you don't have to use all its features, or even implement MVVM pattern. It just has a lot of nice 'tools' you can leverage.
There are a lot of patterns to do it, or you can buy a tool like PostSharp that will do it for you.
For example, here is one method of doing it:
public abstract class BaseNotifyPropertyChanged : INotifyPropertyChanged
{
private Dictionary<string, object> _valueStore = new Dictionary<string, object>();
public event PropertyChangedEventHandler PropertyChanged;
protected T Get<T>([CallerMemberName]string property = null)
{
object value = null;
if (!_valueStore.TryGetValue(property, out value))
return default(T);
return (T)value;
}
protected void Set<T>(T value, [CallerMemberName]string property = null)
{
_valueStore[property] = value;
OnPropertyChangedInternal(property);
}
protected void OnPropertyChanged([CallerMemberName]string property = null)
{
OnPropertyChangedInternal(property);
}
private void OnPropertyChangedInternal(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
Which you then inherit from your classes:
public class PlainOldObject : BaseNotifyPropertyChanged
{
public int MyProperty
{
get { return Get<int>(); }
set { Set(value); }
}
}
Which takes care of the backing store and everything for you. You may want to add logic to only call the OnPropertyChangedInternal if the property actually changed (compare references or value), but I'll leave that as an exercise for you.
Simply use the Observable Object class. Instead of creating a DateTime property, you'd create an ObservableObject<DateTime> and you would just bind to DateClosed.Value.

Is there a way to find out if a property or variable has been set?

As per title, can I find out the history of a property or variable, in terms of whether it has been set or not?
Reason for this is I have some query classes, any properties that have not been set should not be included in the generated query.
Currently I am just trying to add a PropertyInfo instance (I need the name of the property, this is vital to the query generation due to mappings) to a list of properties which have been set in set{}. This is ugly though as it requires more code for what should be classes that only contain properties and no logic (i.e. no removal of stufffrom a list).
Is there something built-in I can use or a more elegant method?
Assuming you're talking about dynamic entities, you could check for null using reflection but this won't tell you anything if the original value was null (or zero in case of numeric data-types).
But best way is to make it implement INotifyPropertyChanged and have a list of properties that have been materialized.
public class Item : INotifyPropertyChanged
{
private List<string> _MaterializedPropertiesInternal;
private List<string> MaterializedPropertiesInternal
{
get
{
if (_MaterializedPropertiesInternal==null)
_MaterializedPropertiesInternal = new List<string>();
return _MaterializedPropertiesInternal;
}
}
private ReadOnlyCollection<string> _MaterializedProperties;
public IEnumerable<string> MaterializedProperties
{
get
{
if (_MaterializedProperties==null) _MaterializedProperties =
new ReadOnlyCollection<string>(MaterializedPropertiesInternal);
return _MaterializedProperties;
}
}
private int _MyProperty;
public int MyProperty
{
get { return _MyProperty; }
set
{
_MyProperty = value;
OnPropertyChanged("MyProperty");
}
}
protected void OnPropertyChanged(string propertyName)
{
if(PropertyChanged != null) PropertyChanged(this,
new PropertyChangedEventArgs(propertyName));
MaterializedPropertiesInternal.Add(propertyName);
}
public event PropertyChangedEventHandler PropertyChanged;
}
Make the properties nullable, e.g. of type int? instead of type int, so that their value is null if they haven't been set.

Categories

Resources