C# 5–Making INotifyPropertyChanged Easier

There are times when I think my friends in the C# team are just listening to me gripe before adding a cool new feature that solves the problem.  (I have never quite outgrown the assumption that the world revolves around me).

A couple years ago I grew really tired of having to create the same old same old when it came to public properties,

private int _myValue;
public int MyValue
{
  get { return _myValue; }
  set { _myValue = value; }
}

 

No sooner did I whine about this, then along came automatic properties and life became much easier.  The above boiled down to

private int MyValue { get; set; }

 

My new gripe (and yours, no doubt) was the work involved in sending in the name of the calling property for INotifyPropertyChanged.  It became common practice to write a helper method that took the name of the property and fed it to the PropertyChanged event, but it was a string being passed around and one tiny typo and your property did not update the UI.  Here’s the old way…

 

private string _name;

public string Name
{
    get { return _name; }
    set
    {
        _name = value;
        RaisePropertyChanged("Name");
    }
}

private void RaisePropertyChanged( string caller)
{
  if (PropertyChanged != null)
  {
    PropertyChanged( this, new PropertyChangedEventArgs( caller ) );
  }
}

 

Notice that the Name property has to send “Name” to the RaisePropertyChanged helper method. 

With C# 5, this problem is solved (Hoot!) by adding an attribute to the argument in RaisePropertyChanged:  [CallerMemberName]  The new syntax, which is much less error prone is:

private string _name;

public string Name
{
    get { return _name; }
    set
    {
        _name = value;
        RaisePropertyChanged();
    }
}

private void RaisePropertyChanged(
    [CallerMemberName] string caller = "" )
{
  if (PropertyChanged != null)
  {
    PropertyChanged( this, new PropertyChangedEventArgs( caller ) );
  }
}

 

Notice that you no longer include the name of the property when calling RaisePropertyChanged.  You just call it, and due to the attribute, the called method figures out what the caller member name is and places that into the string parameter.  Sweet.

Here’s the complete C# for the Employee class for Win 8, followed by the XAML to test it on Win 8…

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace PropertyChanged
{
    class Employee : INotifyPropertyChanged
    {
        private string _name;
        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
                RaisePropertyChanged();
            }
        }

        public void SetName( string newName )
        {
            Name = newName;
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void RaisePropertyChanged( [CallerMemberName] string caller = "")
        {
            if ( PropertyChanged != null )
            {
                PropertyChanged( this, new PropertyChangedEventArgs( caller ) );
            }
        }
    }
}

 

The XAML…

<Page
    x:Class="PropertyChanged.MainPage"
    IsTabStop="false"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:PropertyChanged"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <StackPanel Orientation="Horizontal">
        <TextBlock
            Name="NameDisplay"
            Text="{Binding Name}" />
            <Button
                Height="100"
                Width="200"
                Content="Change name"
                Name="ChangeName"
                Click="ChangeName_Click_1" />
        </StackPanel>
    </Grid>
</Page>

 

The code-behind…

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;


namespace PropertyChanged
{

    public sealed partial class MainPage : Page
    {

        Employee emp = new Employee();

        public MainPage()
        {
            this.InitializeComponent();
        }

       
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            DataContext = emp;
            emp.SetName( "Joe" );
        }

        private void ChangeName_Click_1( object sender, RoutedEventArgs e )
        {
            emp.SetName( "Bob" );
        }
    }
}

About Jesse Liberty

Jesse Liberty has three decades of experience writing and delivering software projects and is the author of 2 dozen books and a couple dozen online courses. His latest book, Building APIs with .NET will be released early in 2025. Liberty is a Senior SW Engineer for CNH and he was a Senior Technical Evangelist for Microsoft, a Distinguished Software Engineer for AT&T, a VP for Information Services for Citibank and a Software Architect for PBS. He is a Microsoft MVP.
This entry was posted in Essentials, Languages, Windows 8 and tagged . Bookmark the permalink.

77 Responses to C# 5–Making INotifyPropertyChanged Easier

  1. Anonymous says:

    This page hangs in Safari and Chrome!

    • Anonymous says:

      It hangs in Firefox too with an error that the javascript times out and the option to wait, cancel or debug…

  2. Your style is so unique in comparison to
    other folkks I’ve rdad stuff from. Many thanks for
    posting when you have tthe opportunity, Guess I will just book mark this page.

    Feeel free too visit my webpage; offering; scatter.dpi.me,

  3. Here in this portal you will get all information regarding 2015 exam results,
    jee main answer key 2015, jee main reuslt, cbse 10th result, cbse 12th results
    2015, entrance exam, viteee, srmeee.

  4. I know this if off topic but I’m looking into starting
    my own blog and was curious what all is needed to get setup?
    I’m assuming having a blog like yours would cost a pretty
    penny? I’m not very internet smart so I’m not 100% certain. Any tips
    or advice would be greatly appreciated. Kudos

    my web site computer technician

  5. korta.st says:

    Pretty! This has been an extremely wonderful article.
    Thank you forr supplying these details.

  6. Fine way of describing, and good paragraph to take data regarding my presentation focus, which i am going
    to present in institution of higher education.

    Stop by my web page – quick unsecured loans

  7. I’ve read some just right stuff here. Certainly value bookmarking for revisiting.

    I wonder how so much effort you place to make this type
    of wonderful informative site.

    Look at my webpage Odzież reklamowa efektywną reklamą

  8. I do not even know how I stopped up here, however
    I thought this post was good. I don’t recognise who you are but certainly you’re going to a well-known blogger if you are not already.
    Cheers!

    Feel free to visit my webpage … benefiance concentrated anti-wrinkle eye cream

  9. Definitely believe that which you stated. Your favourite reason appeared to be on the web the simplest thing to take note of.
    I say to you, I definitely get irked even as folks consider
    concerns that they just do not know about. You managed to hit the nail upon the
    highest as well as defined out the entire thing with
    no need side effect , folks could take a signal.
    Will probably be again to get more. Thanks

  10. If some one desires expert view regarding blogging then i propose him/her
    to go to see this web site, Keep up the pleasant work.

    Stop by my web blog … karatbars international compensation

  11. It’s very trouble-free to find out any topic on net as compared to books,
    as I found this post at this website.

  12. I loved as much as you will receive carried out right here.
    The sketch is tasteful, your authored subject matter stylish.

    nonetheless, you command get got an edginess over that you wish be delivering the following.
    unwell unquestionably come further formerly again as
    exactly the same nearly a lot often inside case you shield this
    hike.

    Here is my webpage affiliate marketing programs for beginners

  13. youtube.com says:

    Thank you for the auspicious writeup. It if truth be told was a amusement account it.
    Glance advanced to more brought agreeable from you!
    By the way, how can we be in contact?

  14. Best Place To Buy youth Nets jersey

  15. A perfect decorating cork will well suit the kid’s room, the children are too rough and handle things in a very
    arrogant way, the kids will bounce the ball on the walls or will throw
    up heavy stuffs on the walls, or they will also scribble their favorite quotes or slogans or animate their favorite
    cartoon character. When you have to make basically the right feel for your inward part space, whether it is a
    striking choice for the room or an enchanting and master feel
    in an office, the masters are the specific authorities
    to call. The process of residential painting is not the most fun activity to perform,
    but if you make it enjoyable by doing it with a friend and good music, interior painting, as well as that of the exterior of your
    home, can be a more pleasant experience.

  16. Thinking about the job at hand, and if you realize that you
    just don’t have the skills or the time to do the job right, then you may want
    to consider hiring a painting contractor to come in and paint your home for you.
    In the event you drive with a house that has a sign proclaiming what house painting company is
    working as well as has worked on a house, this is the sign how
    the homeowner can be harpy with the function and is happy to let the business have some no cost advertizing.
    Painting a house is usually only done once every 7
    years; with enough time and effort dedicated to painting your house, you will be absolutely satisfied with it until
    the next time that you decide to paint.

  17. Victims in an automobile accident commonly include motorists,
    passengers, pedestrians, and even the particular spouse of an injured
    individual that was not in the actual accident but is a victim suffering loss.
    If a staff member might have been provided with personal protective tools but is
    unable to put on it, and they then come into contact with moving machines,
    their workplace is going to be considered to get behaved negligently
    by failing to defend risky device components.
    The reason for this is due to the fact that they have gone to court for personal injury settlements before concerning other people, so you are working with someone who
    knows how to handle this type of case.

  18. vms signs says:

    Hi there to all, hhow is the whole thing, I think every
    one is gettiing more from this website, and your views arre nice
    desiggned for new users.

  19. James Portelli says:

    I know this is an old post, but I had found this years ago and it works like a charm, checking for equality as well. The setter is reduced to one line too! Best of all worlds.

    public event PropertyChangedEventHandler PropertyChanged;

    private void SetProperty(ref T field, T value, [CallerMemberName] string name = “”)
    {
    if (!EqualityComparer.Default.Equals(field, value))
    {
    field = value;
    var handler = PropertyChanged;
    if (handler != null)
    {
    handler(this, new PropertyChangedEventArgs(name));
    }
    }
    }

  20. Eon says:

    I have been reading a lot of article about property changed this one made more sense than the rest and the code I feel is a bit easier to understand. How would though I use you’re method in C# I have the class working fine but implimenting it seems a bit more difficult (still very green on C# and XAML also hell I barely use XAML)

  21. Adam says:

    Thank you for the good writeup. It actually was a amusement account it.
    Glance advanced to more brought agreeable from you! By the way, how can we keep in touch?

  22. hello there annd thank you ffor your info – I have crrtainly picked up something new from
    right here. I did however expertise a few technical points using this site, as I experienced to reload
    the site lots of times previous to I could get it to load correctly.
    I had been wondering if your web host is OK? Not that I’m complaining, but sluggish loading instances times will very frequently affect your placement in google and could damage your high-quality score if advertising and marketing with
    Adwords. Well I’m adding this RSS to my e-mail and could look out
    for a lot more of your respective interesting content.
    Make sure you update this again soon.

  23. Sal says:

    My brother recommended I might like this blog. He was totally right.
    This post truly made my day. You cann’t imagine just how much time I had spent for this information!
    Thanks!

    • Moon says:

      This is exactly what I was looking for. Everywhere on MSDN they tell you how to write the class using INotifyPropertyChanged interface. But, none shows how to bind the property on the client/WPF side demonstrating a complete end to end solution.

      This was very helpful for me. Thanks a ton!

  24. This post provides clear idea in support of the new visitors of blogging, that in fact how to do running a blog.

  25. When it arrives to figuring out all the ins and outs of a video
    game|especially the kinds on your phone|you could spend 1000’s of hours on
    conclude striving to defeat it this is why Sweet Crush Saga Reside Device 3.8.five was created!
    For you avid gamers to consider edge of all the specific attribute this
    instrument provides. Not only you will benefits from all these characteristics
    but you will also help oneself beat every single and each degree the frustrated you for a even though.
    No a lot more waiting around hours to get life or have a restricted amount of boosters.
    Now almost everything you wish has been provided in this
    resource and suitable with Facebook|Apple Units (Ipod|Ipad|Iphones) and
    Android phones also.

  26. Mikey says:

    It’s still not enough — we want the simple syntax back.

    Why not something like:

    public string MyProperty { get; set#; }

    where the “#” is a directive of some sort for the [pre]compiler to put all the extra crap in? (or any symbol, the c# team can just pick one.)

    • @Mikey: Your suggestion would require a modification to the language specification in order to provide functionality to the WPF framework. You don’t just change a language to make something work in one (out of many) framework.

      The custom setter must be implemented for the INotifyPropertyChanged due to this being a WPF interface. The only change that could be made at a language level would be that of auto-implementing the getter while letting us define a custom setter.

      • ZokyZ says:

        Actually, INotifyPropertyChanged is not part of WPF framework. You can use INotifyPropertyChanged in contexts without WPF. It is in System.dll the core of .NET. And since C# is designed for .NET such a modification to the language is not that wrong.

        I would really like a new keyword for C# like
        public string Property { get; observed set; }
        or anything like that 🙂

  27. cg says:

    I found a different way of causing a refresh of the data to the screen. I am using classes with automatic properties to retrieve records via LINQ, and really don’t want to set about 1,000 properties to look like this:

    public string Name
    {
    get { return _name; }
    set
    {
    _name = value;
    RaisePropertyChanged();
    }
    }

    What I did was set the DataContext for my fields in a parent node in the XAML, then set it to NULL and back again when I want the data refreshed to the screen. I’m wondering how expensive this is – of course, it’s rebinding all the nodes below that parent node, but it will happen on a user interaction and it will be affecting on the order of 5-40 controls in my case.

    Here is how the code would work using your examples:

    XAML: Add a name to the StackPanel; everything inside ContextAnchor will have the same DataContext.

    Employee class: Just use automatic properties– do not implement INotifyPropertyChanged:

    class Employee
    {
    public string Name { get; set; }
    }

    The code-behind:

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
    ContextAnchor.DataContext = emp;
    emp.SetName( “Joe” );
    }

    private void ChangeName_Click_1( object sender, RoutedEventArgs e )
    {
    emp.SetName( “Bob” );
    ContextAnchor.DataContext = null; // Trigger all the notifications in the XAML (blanks screen controls)
    ContextAnchor.DataContext = emp; // Re-trigger: causes all the data from emp to be copied back to the screen
    }

    On the face of it this seems a crude way to post back to the screen, but it reduces code size
    and (in my opinion) shows exactly what the developer is trying to do: force a post-to-screen.

    I have not seen this method suggested anywhere and I wonder why. It seems like a reasonable alternative. Love to hear your comments… Does this method make sense? Is it dangerous in some way?

    • cg says:

      My XAML got wiped because of the LTs and GTs.
      The only line that matters is this one:
      [StackPanel Name=”ContextAnchor” Orientation=”Horizontal”]

      • This can be very expensive, depending on the hardware you’re running on. WPF uses reflection under the hood to perform all of the binding. If the binding is taking place with 1,000 objects on screen, it will be very expensive. If you are just binding to a sub-set of those 1,000 objects during each bind then it should not be a problem.

  28. A year of MVVM, and I only just spot this post now! Grrrr… Nice simple implementation.

    I do agree with the vast proportion of responses. There should be an attribute we can add for this, handled under the lid, rather than having to implement our own wrapper for raising the change event. Something like;


    [Observable]
    Public Property MyProperty As String

    This would be nice and neat for me…

  29. The simples solution should be a one like David Vennikov wrote:


    [NotifyPropertyChanged]
    public string Name { get; set; }

    But how make it works without a weaving tool (Simon Cropp) or customizing the type descriptors (not available for SL)?

    For instance, this project (http://catel.codeplex.com/) comes with a solution to avoid write tons of code but is not only available for SL (type descriptors).


    public class PersonViewModel : ViewModelBase
    {
    public static readonly PropertyData PersonProperty = RegisterProperty("Person", typeof(Person), default(Person), null, false);

    [Model]
    [Expose("FirstName")]
    [Expose("LastName")]
    [Expose("Age")]
    public Person Person
    {
    get { return GetValue(PersonProperty); }
    set { SetValue(PersonProperty, value); }
    }
    }

  30. Rob Ainscough says:

    Yeah, why can’t this just be an attribute or better yet a handles defined for the Property when it’s added to the class? Something like:

    Public Class UIUser

    Private _client As Clients
    Public Property Client() As Clients
    Get
    Return _client
    End Get
    Set(ByVal value As Clients) Handles PropertyChanged
    _client = value
    End Set
    End Property

    ….

    The Binding defined in the XAML i.e. Content={Binding Client} has to match up anyway.

    Rob

  31. Wilson says:

    Why doesn’t Microsoft raise the notification behind the scenes, just for the fact the property is chamging the CLR should take care of it and not oblige us to add that code.

  32. Pravin says:

    Could you please share what you are using to embed code in our blog posts?
    Thanks!

  33. Pravin says:

    Not sure why you have a SetName() method in class and calling it:
    emp.SetName( “Joe” );

    Wouldn’t emp.Name = “Joe” do the same thing?

  34. Zdenek Heller says:

    I’ve spent some time on solving INPC repetition code issue. I’ve decided to use AOP from castle windsor. Look at my code on http://code.google.com/p/rrsl-lite/source/browse/trunk/App.Test/RrslLiteTEST/EntityAopTEST.cs .
    The usage is simple – just on entity call CreateProxy() extension method and it will recursively go thru the object tree and creates AOP proxy, which implements INPC
    interface with necessary plumbing code.
    And one feature which is quite hard to code and support later by plumbing code – it can handle “dependent nonPerzistent” properties over instances.
    It is quite hard to explain it within short space, please if you are interested, look at the test class.

  35. Phil Freeman says:

    I prefer passing a lambda expression as the argument to RaisePropertyChanged, because errors can be caught at compile-time, unlike using string, and passing a lambda body does not exhibit the same instability under refactoring that I imagine this code does (I assume ‘Extract Method’ on a long setter breaks this code…)

  36. Simon Cropp says:

    Would it not be better to use ILWeaving http://code.google.com/p/notifypropertyweaver/


    public class Person : InotifyPropertyChanged
    {
        public string GivenNames { get; set; }
    }

    And have it compiled to this


    public class Person : InotifyPropertyChanged
    {
            string givenNames;
        public string GivenNames
        {
            get { return givenNames; }
            set
            {
                if (value != givenNames)
                {
                    givenNames = value;
                    OnPropertyChanged("GivenNames");
                }
            }
        }
    }

    • At the moment, it does not support Win8.

      • Simon Cropp says:

        Jesse

        It does support Windows 8. I had just not updated the doco.
        I have fixed the doco

    • Sridhar Nathani says:

      The ‘caller’ parameter is optional on the RaisePropertyChanged method. If you would like to use it in old ways as you can still pass whatever the string you want.

      The same property ‘Name’ can be written and notify as:
      private string _name;
      public string Name
      {
      get { return _name; }
      set {
      _name = value;
      RaisePropertyChanged(“MyName”);
      }
      }

  37. Oleg says:

    I never understood the obsession about solving string constant “problem” in raising event within the setter.
    It’s not a problem at all! You change the name of property – you see right next to it that the string parameter also have to be changed.
    The real problem is that consumption of event in XAML is also relies on name, not done through strongly typed association.
    And somehow we have a huge number of solutions to overcome little annoyance with no one even talking about real problem which costs you hours of work to find why and where binding is not working anymore.

    • I agree that this is a relatively trivial problem, but the solution is simple and elegant.

      It is interesting to me how many comments this post has generated; clearly some folks are looking for a better way to do this, and I have to tell you that while I certainly agree that difficult to find bugs are the higher priority, not having to do stupid repetitive tasks is also a pretty high priority 🙂

      -j

    • Mark says:

      AND, if you happen to remember to change the literal because it is “right next door”, you also have to TYPE it correctly. And if you have a typo in it, the compiler won’t catch it. And you app will be broken because the property change won’t be raised properly and it make take you a WHILE to figure out what broke the binding that doesn’t work anymore.

    • Krel says:

      You are so wrong on many occassions. The event can be fired on multiple setters.

      Assume, you have FirstName, LastName and FullName properties.

      When FirstName changes, you also need to fire Notifications for both, FirstName AND FullName. Otherwise only one will be updated.

      public string FirstName {
      get { … }
      set {
      firstName = value;
      RaisePropertyChanged(); // notifiy FirstName change
      RaisePropertyChanged(“FullName”); // notify FullName change
      }
      }

      So it’s easy to forget it on one place and you got a bug in your app

  38. Mark says:

    I guess that is an improvement. In Delphi Prism (RemObjects Oxygene) I have been doing it this way for a long time:

    property Name : String; notify;

    That takes care of it being a property, doing notification, and having a default backing field.

    I like Delphi Prism a lot. Far better than C#, imho. It is simpler and does some really nice things. I like that its object interface is separate from the implementation too. That makes it a lot easier to look at a class and tell what it does and what properties it has without having to visually parse through a bunch of method implementation code.

    • Mark says:

      I should also mention (in case Microsoft wants to model C# after Delphi some more) that if you want a property notification on a different name than the property name, you can do that like this:

      property Name : String; notify ‘MyName’;

  39. Stimul8d says:

    This is a step in the right direction but how’s about we just support MVVM out of the box like ASP does MVC? Don’t give me easier inpc, compile them in!

  40. Martin Randall says:

    I’d be interested in knowing what the caller name attribute was intended for other than this very situation. It cover’s probably 80% of view model stuff for Xaml, but as has been pointed out, often you want one property update to reflect changes in other properties and then you are back to passing strings values containing property names around. I think I still prefer using Linq expressions as used in Prism. I know many people might complain that this is a much slower method, but then again – how often are you updating a view model and wanting to fire a NotifyPropertyChanged event?!
    In any case, thanks for sharing this Jesse.

  41. Phil Murray says:

    +1 to David Vennikov

    Why can’t this be done via attributes or even an new property type

  42. David Vennikov says:

    I still miss some simplicity in this solution.
    I would really love to have an attribute that will be added to the property that you want to raise PropertyChanged event when it gets set, without the need to create a backing field.

    e.g:
    [NotifyPropertyChanged]
    public string Name { get; set; }

    • Luetm says:

      I agree, or

      public observable string Name { get; set; }

    • Peter says:

      That’s what i was thinking, stick an attribute to it and just leave it at that… now that would have been a great productivity booster! But as someone else mentions… it should not be necessary in the first place that we do this…

  43. David Vennikov says:

    I’m still missing some simplicity in this solution.
    I would really love to have an attribute that will be added to the property that you want to raise PropertyChanged event when it gets set, without the need to create a backing field.

    e.g:
    [NotifyPropertyChanged]
    public string Name { get; set; }

  44. Fizz says:

    Very nice, how about cleaning up the need for class scoped field as well, i.e.

    public string Name
    {
    string name;
    get { return name;}
    set { name = value; PropertyChanged(); }
    }

  45. Martin R says:

    @david: No this is not reflection. It’s done by the compiler. See Caller Info values are emitted as literals into the Intermediate Language (IL) at compile time. Unlike the results of the StackTrace property for exceptions, the results aren’t affected by obfuscation.

  46. david says:

    How about speed? CallerMemberName is a function in reflection. And we all know reflection can be slow.

  47. Colin Blair says:

    One thing that may not be obvious is that the [CallerMemberName] is only changing the default value passed into RaisePropertyChange. If you want to call your RaisePropertyChange and still supply the property name you can do thought without having to overload RaisePropertyChange. This can be very useful when you have properties that can change values without the set being called. For example, a FullName property that relies on the values of FirstName and LastName.

  48. Bas Hamer says:

    I like that, a lot.

    I’ll probably still keep a baseclass and do the equality checks, but yeah I like how it makes things easier. This is the code right now and a lot of that is about to get cleaned up; really makes refactoring much safer.

    this is where I’m at now, but it is still prone to refactoring / renaming; this feature will fix that.


    [Serializable]
    [DataContract]
    public abstract class NotifyPropertyChangedBase : INotifyPropertyChanged
    {
    protected void NotifyPropertyChanged(String info)
    {
    if (PropertyChanged != null)
    {
    PropertyChanged(this, new PropertyChangedEventArgs(info));
    }
    }

    ///
    /// this should all be handled trough the properties.
    ///
    [NonSerialized]
    protected Dictionary _values = new Dictionary();

    ///
    /// this is how you use it
    ///
    private string Sample
    {
    get
    {
    return Get("Sample");
    }

    set
    {
    Set("Sample", value);
    }
    }

    protected T Get(string propname)
    {
    if (!_values.ContainsKey(propname))
    {
    if(typeof(T).IsClass)
    _values.Add(propname, null);
    else
    _values.Add(propname, Activator.CreateInstance());
    }
    return (T)_values[propname];
    }

    protected void Set(string propname, T value) where T : IEquatable
    {
    if (value==null || !value.Equals(Get(propname)))
    {
    _values[propname] = value;
    NotifyPropertyChanged(propname);
    }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    }

Comments are closed.