1

I am just wondering is it possible to do something like this:

private int _x;
public int X 
{
get{ return _x;}
set{_x = value; OnPropertyChanged(*theNameOfTheProperty*);}
}

without actually specifying OnPropertyChanged("X");

I guess making OnPropertyChanged more generic maybe using reflection...

jharr100
  • 1,449
  • 24
  • 51
  • You can do it with `Expression`s. It's used in `Prism` for instance, so that you write `OnPropertyChanged(() => MyProperty);` – default Jun 26 '14 at 20:33
  • 1
    [check out this question](http://stackoverflow.com/questions/7728465/implementing-notifypropertychanged-without-magic-strings). Is that what you are looking for? – default Jun 26 '14 at 20:34
  • If you are using c# 5.0, then the [CallerMemberName](http://grenangen.se/node/75) attribute is really handy here. – Matt Burland Jun 26 '14 at 20:34
  • With Prism and `BindableBase` you just do `set { SetProperty(ref myProperty, value); }` btw. That's *really* easy. – default Jun 26 '14 at 20:36

2 Answers2

5

There are two ways to sort of do what you are asking. The first (.NET 4.5+ only!) way to do it is to modify OnPropertyChanged to:

private void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
 ....
}

Then you call it from the setter:

set
{
   _var = value;
   OnPropertyChanged();
}

This will automatically populate the "propertyName" argument with the calling property, unless you provide the argument explicitly. Note you need a using System.Runtime.CompilerServices; to get the namespace for the CallerMemberName attribute.

The other way would be to write a custom version of the propfull snippet to populate it for you at creation time. My version of this snippet is:

<?xml version="1.0" encoding="utf-8" ?>
<CodeSnippets  xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
    <CodeSnippet Format="1.0.0">
        <Header>
            <Title>propnp</Title>
            <Shortcut>propnp</Shortcut>
            <Description>Code snippet for property with OnPropertyChanged</Description>
            <Author>Bradley</Author>
            <SnippetTypes>
                <SnippetType>Expansion</SnippetType>
            </SnippetTypes>
        </Header>
        <Snippet>
            <Declarations>
                <Literal>
                    <ID>type</ID>
                    <ToolTip>Property type</ToolTip>
                    <Default>int</Default>
                </Literal>
                <Literal>
                    <ID>property</ID>
                    <ToolTip>Property name</ToolTip>
                    <Default>MyProperty</Default>
                </Literal>
                <Literal>
                    <ID>field</ID>
                    <ToolTip>The variable backing this property</ToolTip>
                    <Default>myVar</Default>
                </Literal>
            </Declarations>
            <Code Language="csharp"><![CDATA[public $type$ $property$
    {
        get { return $field$;}
        set 
        { 
            $field$ = value;
            OnPropertyChanged($property$);
        }
    }
    $end$]]>
            </Code>
        </Snippet>
    </CodeSnippet>
</CodeSnippets>
BradleyDotNET
  • 60,462
  • 10
  • 96
  • 117
4

You can declare your OnPropertyChanged this way:

    protected void OnPropertyChanged([CallerMemberName] string name = "")
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }

Then you can invoke it like that from the property:

    public IEnumerable<Customer> Customers
    {
        get
        {
            return this.customers;
        }
        set
        {
            this.customers = value;
            this.OnPropertyChanged();
        }
    }
PiotrWolkowski
  • 8,408
  • 6
  • 48
  • 68