If the property event will trigger I want a method that will be called
For example. If the name of person is changed the MethodOne() will be also called. How to implement this with INotifyPropertyChanged on another class for example on WPF MainWindow.xaml.cs? Thank You
public class ObservableObject : INotifyPropertyChanged
{
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler? PropertyChanged;
}
...
There a few ways that you can get notified of property changed.
Generally you should always define properties using DependencyProperty.Register and then add access methods.
In the example that follows change YourClass to be your class name.
Declare the property like this, note that the new PropertyMetadata specifies a static method to call when the property is changed. This can be useful but is optional and can be omitted.
/// <summary>
/// Backs the IsBusy dependency property.
/// </summary>
public static readonly DependencyProperty IsBusyProperty =
DependencyProperty.Register(
"IsBusy",
typeof( bool ),
typeof( YourClass ),
new PropertyMetadata( false, new PropertyChangedCallback( OnIsBusyChanged ) ) );
then provide an access method that will use the underlying backing property, so that any changes can be tracked.
/// <summary>
/// Gets or sets a value indicating whether the busy indicator should show.
/// </summary>
public bool IsBusy
{
get
{
return ( bool )GetValue( IsBusyProperty );
}
set
{
SetValue( IsBusyProperty, value );
}
}
The following is the static interface to the dependency property that is required to be static. In here we will receive the dependency object that will usually be an instance of your class and thus we can invoke an object method from that class.
/// <summary>
/// IsBusyProperty property changed handler.
/// </summary>
/// <remarks>
/// This is the static version that is invoked by the dependency property
/// with the appropriate object, so see if d is our class and if so then
/// we can invoke the method on the class
/// </remarks>
/// <param name="d">Instance of class that changed its IsBusy.</param>
/// <param name="e">Event arguments.</param>
private static void OnIsBusyChanged( DependencyObject d, DependencyPropertyChangedEventArgs e )
{
if (d is YourClass)
{
var bb = d as YourClass;
bb.OnIsBusyChanged(e);
}
}
and finally the method that will be called when the property is changed in the object
/// <summary>
/// IsBusyProperty property changed handler.
/// </summary>
/// <param name="e">Event arguments.</param>
protected virtual void OnIsBusyChanged(DependencyPropertyChangedEventArgs e)
{
// your code
// you could notify a parent or another event
// handler
}
As an alternative you can directly attach to the PropertyChanged event.
In your constructor (or somewhere)
PropertyChanged += somePropertyChanged;
this will then call the method somePropertyChanged which is defined as follows:
private void somePropertyChanged(object sender, PropertyChangedEventArgs e)
{
// sender is the object that caused the change
// and is usually your class
Console.WriteLine("Property {0} changed", e.PropertyName);
}
The first approach of specifying a callback in DependencyProperty.Register can be useful when you have a set of properties that can be considered as a group and when a similar action will be taken.
Related
I wish to use attached properties in my application by making use of the code below (and taken from here). However, Intellisense in Visual Studio will not show the registered Attached Properties for some reason unknown to me. My application is an add-in and constrained to be a class library (.Net Framework 4.7.2)
Viewing the code below and taking cognizance of the definition for Attached Properties, I would think that the attached property would be defined as such
public static readonly DependencyProperty ValueProperty = DependencyProperty.RegisterAttached(
"Value",
typeof(Property),
**typeof(Parent)**,
new UIPropertyMetadata(
default(Property),
new PropertyChangedCallback(OnValuePropertyChanged),
new CoerceValueCallback(OnValuePropertyUpdated)
));
and NOT as such
public static readonly DependencyProperty ValueProperty = DependencyProperty.RegisterAttached(
"Value",
typeof(Property),
**typeof(BaseAttachedProperty<Parent, Property>)**,
new UIPropertyMetadata(
default(Property),
new PropertyChangedCallback(OnValuePropertyChanged),
new CoerceValueCallback(OnValuePropertyUpdated)
));
Notice the difference between typeof(Parent) and typeof(BaseAttachedProperty<Parent, Property>). However, when I use this code in a Visual Studio Class Library, Intellisense does not show the defined Attached Properties that are defined for example:
public class IsBusyProperty : BaseAttachedProperty<IsBusyProperty, bool>
{
}
Intellisense shows the cryptic information: local:BaseAttachedProperty`2.Value which I understand refers to the Base Class with two parameters. Is there some particular method to handle Generics and Base Classes with WPF so that Attached Properties are recognized as being in this Namespace and also being consumable? My goal is to ease the creation and consumption of Attached Properties in my application. I have done the cleaning, deletion of the bin folder to no avail. However, when I write an own AP for example:
public class IsBusyProperty
{
public static readonly DependencyProperty ValueProperty =
DependencyProperty.RegisterAttached("Value", typeof(bool), typeof(IsBusyProperty), new PropertyMetadata(false));
public static bool GetValue(DependencyObject obj)
{
return (bool)obj.GetValue(ValueProperty);
}
public static void SetValue(DependencyObject obj, bool value)
{
obj.SetValue(ValueProperty, value);
}
}
the code compiles without the dreaded error that the attached property is not found in the namespace local:... or the No implementation exception!
Here is the reference code taken from here.
using System;
using System.ComponentModel;
using System.Windows;
namespace Fasetto.Word
{
/// <summary>
/// A base attached property to replace the vanilla WPF attached property
/// </summary>
/// <typeparam name="Parent">The parent class to be the attached property</typeparam>
/// <typeparam name="Property">The type of this attached property</typeparam>
public abstract class BaseAttachedProperty<Parent, Property>
where Parent : new()
{
#region Public Events
/// <summary>
/// Fired when the value changes
/// </summary>
public event Action<DependencyObject, DependencyPropertyChangedEventArgs> ValueChanged = (sender, e) => { };
/// <summary>
/// Fired when the value changes, even when the value is the same
/// </summary>
public event Action<DependencyObject, object> ValueUpdated = (sender, value) => { };
#endregion
#region Public Properties
/// <summary>
/// A singleton instance of our parent class
/// </summary>
public static Parent Instance { get; private set; } = new Parent();
#endregion
#region Attached Property Definitions
/// <summary>
/// The attached property for this class
/// </summary>
public static readonly DependencyProperty ValueProperty = DependencyProperty.RegisterAttached(
"Value",
typeof(Property),
typeof(BaseAttachedProperty<Parent, Property>),
new UIPropertyMetadata(
default(Property),
new PropertyChangedCallback(OnValuePropertyChanged),
new CoerceValueCallback(OnValuePropertyUpdated)
));
/// <summary>
/// The callback event when the <see cref="ValueProperty"/> is changed
/// </summary>
/// <param name="d">The UI element that had it's property changed</param>
/// <param name="e">The arguments for the event</param>
private static void OnValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// Call the parent function
(Instance as BaseAttachedProperty<Parent, Property>)?.OnValueChanged(d, e);
// Call event listeners
(Instance as BaseAttachedProperty<Parent, Property>)?.ValueChanged(d, e);
}
/// <summary>
/// The callback event when the <see cref="ValueProperty"/> is changed, even if it is the same value
/// </summary>
/// <param name="d">The UI element that had it's property changed</param>
/// <param name="e">The arguments for the event</param>
private static object OnValuePropertyUpdated(DependencyObject d, object value)
{
// Call the parent function
(Instance as BaseAttachedProperty<Parent, Property>)?.OnValueUpdated(d, value);
// Call event listeners
(Instance as BaseAttachedProperty<Parent, Property>)?.ValueUpdated(d, value);
// Return the value
return value;
}
/// <summary>
/// Gets the attached property
/// </summary>
/// <param name="d">The element to get the property from</param>
/// <returns></returns>
public static Property GetValue(DependencyObject d) => (Property)d.GetValue(ValueProperty);
/// <summary>
/// Sets the attached property
/// </summary>
/// <param name="d">The element to get the property from</param>
/// <param name="value">The value to set the property to</param>
public static void SetValue(DependencyObject d, Property value) => d.SetValue(ValueProperty, value);
#endregion
#region Event Methods
/// <summary>
/// The method that is called when any attached property of this type is changed
/// </summary>
/// <param name="sender">The UI element that this property was changed for</param>
/// <param name="e">The arguments for this event</param>
public virtual void OnValueChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { }
/// <summary>
/// The method that is called when any attached property of this type is changed, even if the value is the same
/// </summary>
/// <param name="sender">The UI element that this property was changed for</param>
/// <param name="e">The arguments for this event</param>
public virtual void OnValueUpdated(DependencyObject sender, object value) { }
#endregion
}
}
I am having some trouble with initializing a new variable as the object being sent by the global property changed. I have two classes BeltConfiguration and BeltProperty (both classes have INotifyPropertyChanged). I have a globalpropertychanged method in the BeltConfiguration class as seen here.
private void BeltProperty_GlobalPropertyChanged(object sender, PropertyChangedEventArgs e)
{
BeltProperty validBelt = sender as BeltProperty;
if (validBelt != null)
{
this.Validation = validBelt.Validation;
}
switch (e.PropertyName)
{
case "Value":
this.Validation.ValidState = ConfigurationValid.Unknown;
OnPropertyChanged("Validate");
break;
case "ConfigurationInvalid":
this.Validation.ValidState = ConfigurationValid.False;
OnPropertyChanged("Validate");
break;
}
}
In the BeltProperty class, I call this with OnGlobalPropertyChanged("ConfigurationInvalid");
However, when I call it, no matter what I do, validBelt always results in being null. I looked at the object sender by stepping through the code and it says that the declaring method, GenericParametersAttributes, and GenericParametersPosition threw an exception of System.InvalidOperationException. I don't know if that has anything to do with why validBelt won't accept sender as BeltProperty. Thanks for any help or advice you can give me.
This is where I called BeltProperty_GlobalPropertyChanged in the Belt Property class.
private ConfigurationValidation _Validation = new ConfigurationValidation(ConfigurationValid.Unknown, "", "", null);
/// <summary>
/// Stores information as to wether this belt property is valid or invalid, and the details.
/// </summary>
internal ConfigurationValidation Validation
{
get { return _Validation; }
set {
_Validation = value;
if(_Validation.ValidState == ConfigurationValid.False)
{
OnGlobalPropertyChanged("ConfigurationInvalid");
}
}
}
/// <summary>
/// A global on property change that runs for any instantiated object of this type.
/// </summary>
/// <param name="name"></param>
static void OnGlobalPropertyChanged(string name)
{
GlobalPropertyChanged(
typeof(BeltProperty),
new PropertyChangedEventArgs(name));
}
Since you are using a safe cast here:
BeltProperty validBelt = sender as BeltProperty
When validBelt is null after this assignment it means sender cannot be cast to an instance of BeltProperty.
Looking at your calling code it looks like you are not passing an instance of BeltProperty into your event handler.
Assuming GlobalPropertyChanged is your PropertyChangedEventHandler delegate change your OnGlobalPropertyChanged code to this:
/// <summary>
/// A global on property change that runs for any instantiated object of this type.
/// </summary>
/// <param name="name"></param>
static void OnGlobalPropertyChanged(string name)
{
GlobalPropertyChanged(
this,
new PropertyChangedEventArgs(name)
);
}
How can I create a simple bool dependency property IsInput. This value can only be set to true or false when the class is created in code. Seems rather simple but ive searched around online and haven't found a clear example.
I've seen examples like this one below online but I'm not quite clear on what I would duplicate to create my own bool dependency property correctly.
public static readonly DependencyProperty AncestorProperty =
DependencyProperty.Register("Ancestor", typeof(FrameworkElement), typeof(MyItem),
new FrameworkPropertyMetadata(Ancestor_PropertyChanged));
/// <summary>
/// Event raised when 'Ancestor' property has changed.
/// </summary>
private static void Ancestor_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
MyItem c = (MyItem)d;
c.UpdateHotspot();
}
The second parameter of the Register method is the type of the property, i.e. bool, while the third parameter is the so-called owner type, which is the type that declares the property (MyControl in the example below).
For a complete dependency property declaration you also need to declare the "wrapper" property with a getter and a setter that call the dependency property's GetValue and SetValue methods.
public static readonly DependencyProperty IsInputProperty =
DependencyProperty.Register("IsInput", typeof(bool), typeof(MyControl),
new FrameworkPropertyMetadata(IsInputPropertyChanged));
/// <summary>
/// CLR wrapper for the 'IsInput' dependency property.
/// </summary>
public bool IsInput
{
get { return (bool)GetValue(IsInputProperty); }
set { SetValue(IsInputProperty, value); }
}
/// <summary>
/// Callback called when 'IsInput' property has changed.
/// </summary>
private static void IsInputPropertyChanged(
DependencyObject d, DependencyPropertyChangedEventArgs e)
{
bool b = (bool)e.NewValue;
//TODO
}
I want to change an image source from different classes (pages) including a settings flyout
I was acknowledged that i have to make the image as a global variable. But couldn't figure out how to do it. Is there any other way ?
Since you want a change to affect all pages - a shared view model is your best option. Create your view model class first:
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace App.ViewModel
{
public sealed class MyViewModel : INotifyPropertyChanged
{
#region BindableBase implementation
/// <summary>
/// Multicast event for property change notifications.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Checks if a property already matches a desired value. Sets the property and
/// notifies listeners only when necessary.
/// </summary>
/// <typeparam name="T">Type of the property.</typeparam>
/// <param name="storage">Reference to a property with both getter and setter.</param>
/// <param name="value">Desired value for the property.</param>
/// <param name="propertyName">Name of the property used to notify listeners. This
/// value is optional and can be provided automatically when invoked from compilers that
/// support CallerMemberName.</param>
/// <returns>True if the value was changed, false if the existing value matched the
/// desired value.</returns>
protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] String propertyName = null)
{
if (object.Equals(storage, value)) return false;
storage = value;
this.OnPropertyChanged(propertyName);
return true;
}
/// <summary>
/// Notifies listeners that a property value has changed.
/// </summary>
/// <param name="propertyName">Name of the property used to notify listeners. This
/// value is optional and can be provided automatically when invoked from compilers
/// that support <see cref="CallerMemberNameAttribute"/>.</param>
private void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var eventHandler = this.PropertyChanged;
if (eventHandler != null)
{
eventHandler(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
#region MyImage
/// <summary>
/// Backing field for the MyImage property.
/// </summary>
private ImageSource myImage;
/// <summary>
/// Gets or sets a value indicating ....
/// </summary>
public string MyImage
{
get { return this.myImage; }
set { this.SetProperty(ref this.myImage, value); }
}
#endregion
}
}
Then in App.xaml instantiate it as a resource:
<Application
x:Class="App.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewModel="using:App.ViewModel">
<Application.Resources>
<viewModel:MyViewModel
x:Key="MyViewModel"/>
</Application.Resources>
</Application>
Then anywhere you want to use that image put something like:
<Image
Source="{Binding MyImage, Source={StaticResource MyViewModel}"/>
Then when you want to change the image you can do something like this:
((MyViewModel)App.Current.Resources["MyViewModel"]).MyImage = new BitmapImage();
Are you using ViewModel classes to do your codes?
If yes, you can create a BaseViewModel class and there you can place your global property.
And all your viewmodel classes must have to inherit BaseViewModel. So that from any viewmodel you can change or set the Image source by accessing the base class property.
Public class BaseViewModel
{
//place your global properties here
Public string Name {get;set;}
}
Public class ViewModel1:BaseViewModel
{
//you can access the global property here
void Method1()
{
Name="something";
}
}
Public class ViewModel2:BaseViewModel
{
//you can access the global property here
void Method2()
{
Name="something";
}
}
Hope this helps.
Thanks
We have a WPF Project that follows the MVVM pattern.
In the View Model there is a lot of code that looks like this:
private string m_Fieldname;
public string Fieldname
{
get { return m_Fieldname; }
set
{
m_Fieldname = value;
OnPropertyChanged("Fieldname");
}
}
Is there a way to do this that would require less code?
Would be nice with something like this:
[NotifyWhenChanged]
public string Fieldname { get; set ; }
You could have a look at PostSharp. They even have a sample at Data Binding. The code taken from there:
/// <summary>
/// Aspect that, when apply on a class, fully implements the interface
/// <see cref="INotifyPropertyChanged"/> into that class, and overrides all properties to
/// that they raise the event <see cref="INotifyPropertyChanged.PropertyChanged"/>.
/// </summary>
[Serializable]
[IntroduceInterface( typeof(INotifyPropertyChanged),
OverrideAction = InterfaceOverrideAction.Ignore )]
[MulticastAttributeUsage( MulticastTargets.Class,
Inheritance = MulticastInheritance.Strict )]
public sealed class NotifyPropertyChangedAttribute : InstanceLevelAspect,
INotifyPropertyChanged
{
/// <summary>
/// Field bound at runtime to a delegate of the method <c>OnPropertyChanged</c>.
/// </summary>
[ImportMember( "OnPropertyChanged", IsRequired = false)]
public Action<string> OnPropertyChangedMethod;
/// <summary>
/// Method introduced in the target type (unless it is already present);
/// raises the <see cref="PropertyChanged"/> event.
/// </summary>
/// <param name="propertyName">Name of the property.</param>
[IntroduceMember( Visibility = Visibility.Family, IsVirtual = true,
OverrideAction = MemberOverrideAction.Ignore )]
public void OnPropertyChanged( string propertyName )
{
if ( this.PropertyChanged != null )
{
this.PropertyChanged( this.Instance,
new PropertyChangedEventArgs( propertyName ) );
}
}
/// <summary>
/// Event introduced in the target type (unless it is already present);
/// raised whenever a property has changed.
/// </summary>
[IntroduceMember( OverrideAction = MemberOverrideAction.Ignore )]
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Method intercepting any call to a property setter.
/// </summary>
/// <param name="args">Aspect arguments.</param>
[OnLocationSetValueAdvice,
MulticastPointcut( Targets = MulticastTargets.Property,
Attributes = MulticastAttributes.Instance)]
public void OnPropertySet( LocationInterceptionArgs args )
{
// Don't go further if the new value is equal to the old one.
// (Possibly use object.Equals here).
if ( args.Value == args.GetCurrentValue() ) return;
// Actually sets the value.
args.ProceedSetValue();
// Invoke method OnPropertyChanged (our, the base one, or the overridden one).
this.OnPropertyChangedMethod.Invoke( args.Location.Name );
}
}
Usage is then as simple as this:
[NotifyPropertyChanged]
public class Shape
{
public double X { get; set; }
public double Y { get; set; }
}
Examples taken from PostSharp site and inserted for completing the answer
It looks like as if the Framework 4.5 slightly simplifies this:
private string m_Fieldname;
public string Fieldname
{
get { return m_Fieldname; }
set
{
m_Fieldname = value;
OnPropertyChanged();
}
}
private void OnPropertyChanged([CallerMemberName] string propertyName = "none passed")
{
// ... do stuff here ...
}
This doesn't quite automate things to the extent you're looking for, but using the CallerMemberNameAttribute makes passing the property name as a string unnecessary.
If you're working on Framework 4.0 with KB2468871 installed, you can install the Microsoft BCL Compatibility Pack via nuget, which also provides this attribute.
Josh Smith has a good article on using DynamicObject to do this here
Basically it involves inheriting from DynamicObject and then hooking into TrySetMember. CLR 4.0 only, unfortunately, although it may also be possible using ContextBoundObject in earlier versions but that would probably hurt performance, being primarily suited for remoting\WCF.
IMHO, the PostSharp approach, as in the accepted answer, is very nice and is of course the direct answer to the question asked.
However, for those who can't or won't use a tool like PostSharp to extend the C# language syntax, one can get most of the benefit of avoiding code repetition with a base class that implements INotifyPropertyChanged. There are many examples lying around, but none have so far been included in this useful and well-trafficked question, so here is the version I generally use:
/// <summary>
/// Base class for classes that need to implement <see cref="INotifyPropertyChanged"/>
/// </summary>
public class NotifyPropertyChangedBase : INotifyPropertyChanged
{
/// <summary>
/// Raised when a property value changes
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Updates a field for a named property
/// </summary>
/// <typeparam name="T">The type of the field</typeparam>
/// <param name="field">The field itself, passed by-reference</param>
/// <param name="newValue">The new value for the field</param>
/// <param name="onChangedCallback">A delegate to be called if the field value has changed. The old value of the field is passed to the delegate.</param>
/// <param name="propertyName">The name of the associated property</param>
protected void UpdatePropertyField<T>(ref T field, T newValue,
Action<T> onChangedCallback = null,
[CallerMemberName] string propertyName = null)
{
if (EqualityComparer<T>.Default.Equals(field, newValue))
{
return;
}
T oldValue = field;
field = newValue;
onChangedCallback?.Invoke(oldValue);
OnPropertyChanged(propertyName);
}
/// <summary>
/// Raises the <see cref="PropertyChanged"/> event.
/// </summary>
/// <param name="propertyName">The name of the property that has been changed</param>
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
Used, for example, like this:
private int _value;
public int Value
{
get { return _value; }
set { UpdatePropertyField(ref _value, value); }
}
Not quite as concise as being able to just apply a code attribute to an auto-implemented property as in the PostSharp approach, but still goes a long way to speeding the implementation of view models and other similar types.
The key features above that distinguish it from some other implementations:
Equality is compared using EqualityComparer<T>.Default. This ensures that value types can be compared without being boxed (a common alternative would be object.Equals(object, object)). The IEqualityComparer<T> instance is cached, so after the first comparison for any given type T, it's very efficient.
The OnPropertyChanged() method is virtual. This allows derived types to easily and efficiently handle property changed events in a centralized way, without having to subscribe to the PropertyChanged event itself (e.g. for multiple levels of inheritance) and also of course gives the derived type better control over how and when it handles the property changed event relative to raising the actual PropertyChanged event.
Ok this doesn't clean the code up but it shortens the amount of time writing all of this code. I can now blow through a list of 20+ properties in a couple of minutes.
First you need to define all of your private variables, I'm assuming your first character is a lower case. Now copy that those variables into another list as the macro removes the original line.
For example:
private int something1 = 0;
private int something2 = 0;
private int something3 = 0;
private int something4 = 0;
private int something5 = 0;
private int something6 = 0;
Then put your cursor somewhere on that line and run this macro. Again this replaces the line with a public property so make sure you have the same private member variable defined before this in your class.
I'm sure this script could be cleaned up, but it saved me hours of tedious work today.
Sub TemporaryMacro()
DTE.ActiveDocument.Selection.StartOfLine(VsStartOfLineOptions.VsStartOfLineOptionsFirstText)
DTE.ActiveDocument.Selection.Delete(7)
DTE.ActiveDocument.Selection.Text = "public"
DTE.ActiveDocument.Selection.CharRight()
DTE.ExecuteCommand("Edit.Find")
DTE.Find.FindWhat = " "
DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument
DTE.Find.MatchCase = False
DTE.Find.MatchWholeWord = False
DTE.Find.Backwards = False
DTE.Find.MatchInHiddenText = False
DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
DTE.Find.Action = vsFindAction.vsFindActionFind
If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
Throw New System.Exception("vsFindResultNotFound")
End If
DTE.ActiveDocument.Selection.CharRight()
DTE.ActiveDocument.Selection.WordRight(True)
DTE.ActiveDocument.Selection.CharLeft(True)
DTE.ActiveDocument.Selection.Copy()
DTE.ActiveDocument.Selection.CharLeft()
DTE.ActiveDocument.Selection.CharRight(True)
DTE.ActiveDocument.Selection.ChangeCase(VsCaseOptions.VsCaseOptionsUppercase)
DTE.ActiveDocument.Selection.EndOfLine()
DTE.ActiveDocument.Selection.StartOfLine(VsStartOfLineOptions.VsStartOfLineOptionsFirstText)
DTE.ExecuteCommand("Edit.Find")
DTE.Find.FindWhat = " = "
DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument
DTE.Find.MatchCase = False
DTE.Find.MatchWholeWord = False
DTE.Find.Backwards = False
DTE.Find.MatchInHiddenText = False
DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
DTE.Find.Action = vsFindAction.vsFindActionFind
If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
Throw New System.Exception("vsFindResultNotFound")
End If
DTE.ActiveDocument.Selection.CharLeft()
DTE.ActiveDocument.Selection.EndOfLine(True)
DTE.ActiveDocument.Selection.Delete()
DTE.ActiveDocument.Selection.NewLine()
DTE.ActiveDocument.Selection.Text = "{"
DTE.ActiveDocument.Selection.NewLine()
DTE.ActiveDocument.Selection.Text = "get { return "
DTE.ActiveDocument.Selection.Paste()
DTE.ActiveDocument.Selection.Text = "; }"
DTE.ActiveDocument.Selection.NewLine()
DTE.ActiveDocument.Selection.Text = "set"
DTE.ActiveDocument.Selection.NewLine()
DTE.ActiveDocument.Selection.Text = "{"
DTE.ActiveDocument.Selection.NewLine()
DTE.ActiveDocument.Selection.Text = "if("
DTE.ActiveDocument.Selection.Paste()
DTE.ActiveDocument.Selection.Text = " != value)"
DTE.ActiveDocument.Selection.NewLine()
DTE.ActiveDocument.Selection.Text = "{"
DTE.ActiveDocument.Selection.NewLine()
DTE.ActiveDocument.Selection.Paste()
DTE.ActiveDocument.Selection.Text = " = value;"
DTE.ActiveDocument.Selection.NewLine()
DTE.ActiveDocument.Selection.Text = "OnPropertyChanged("""
DTE.ActiveDocument.Selection.Paste()
DTE.ActiveDocument.Selection.Text = """);"
DTE.ActiveDocument.Selection.StartOfLine(VsStartOfLineOptions.VsStartOfLineOptionsFirstText)
DTE.ExecuteCommand("Edit.Find")
DTE.Find.FindWhat = """"
DTE.Find.Target = vsFindTarget.vsFindTargetCurrentDocument
DTE.Find.MatchCase = False
DTE.Find.MatchWholeWord = False
DTE.Find.Backwards = False
DTE.Find.MatchInHiddenText = False
DTE.Find.PatternSyntax = vsFindPatternSyntax.vsFindPatternSyntaxLiteral
DTE.Find.Action = vsFindAction.vsFindActionFind
If (DTE.Find.Execute() = vsFindResult.vsFindResultNotFound) Then
Throw New System.Exception("vsFindResultNotFound")
End If
DTE.ActiveDocument.Selection.CharRight()
DTE.ActiveDocument.Selection.CharRight(True)
DTE.ActiveDocument.Selection.ChangeCase(VsCaseOptions.VsCaseOptionsUppercase)
DTE.ActiveDocument.Selection.Collapse()
DTE.ActiveDocument.Selection.EndOfLine()
DTE.ActiveDocument.Selection.NewLine()
DTE.ActiveDocument.Selection.Text = "}"
DTE.ActiveDocument.Selection.NewLine()
DTE.ActiveDocument.Selection.Text = "}"
DTE.ActiveDocument.Selection.NewLine()
DTE.ActiveDocument.Selection.Text = "}"
DTE.ActiveDocument.Selection.NewLine()
DTE.ActiveDocument.Selection.LineDown()
DTE.ActiveDocument.Selection.EndOfLine()
End Sub
I'd use PropertyChanged.Fody NuGet package. It's as simple as:
[PropertyChanged.ImplementPropertyChanged]
public class MyViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = (sender, e) => { };
public string Prop1 { get; set; }
public string Prop2 { get; set; }
}
All public properties will raise PropertyChanged event under the hood.
P.S. Syntax changed in newer versions. This example is for version 1.52.1