Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling PropertyChanged in a type-safe way

There have been plenty of articles about how to use reflection and LINQ to raise PropertyChanged events in a type-safe way, without using strings.

But is there any way to consume PropertyChanged events in a type-safe manner? Currently, I'm doing this

void model_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    switch (e.PropertyName)
    {
        case "Property1":
            ...
        case "Property2":
            ...

        ....               
    }
}

Is there any way to avoid hard-coding strings in a switch statement to handle the different properties? Some similar LINQ- or reflection-based approach?

like image 621
kpozin Avatar asked Sep 08 '10 13:09

kpozin


2 Answers

With C# 6.0 you can use nameof. You can also reference a class' property without creating an instance of that class.

void model_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    switch (e.PropertyName)
    {
        case nameof(ClassName.Property1):
            ...
        case nameof(ClassName.Property2):
            ...

        ....               
    }
}
like image 160
mabeale Avatar answered Oct 02 '22 18:10

mabeale


Let’s declare a method that can turn a lambda expression into a Reflection PropertyInfo object (taken from my answer here):

public static PropertyInfo GetProperty<T>(Expression<Func<T>> expr)
{
    var member = expr.Body as MemberExpression;
    if (member == null)
        throw new InvalidOperationException("Expression is not a member access expression.");
    var property = member.Member as PropertyInfo;
    if (property == null)
        throw new InvalidOperationException("Member in expression is not a property.");
    return property;
}

And then let’s use it to get the names of the properties:

void model_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName == GetProperty(() => Property1).Name)
    {
        // ...
    }
    else if (e.PropertyName == GetProperty(() => Property2).Name)
    {
        // ...
    }
}

Unfortunately you can’t use a switch statement because the property names are no longer compile-time constants.

like image 40
Timwi Avatar answered Oct 02 '22 18:10

Timwi