Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PropertyChanged/PropertyChanging, base class and Fody #22

Closed
yanglee opened this issue Oct 14, 2012 · 2 comments
Closed

PropertyChanged/PropertyChanging, base class and Fody #22

yanglee opened this issue Oct 14, 2012 · 2 comments

Comments

@yanglee
Copy link

yanglee commented Oct 14, 2012

When INotifyPropertyChanged / INotifyPropertyChanging declared in a base class that is in another project that is not Fody enabled, I have to manually implement OnPropertyChanged / OnPropertyChanging in the base class.

Here is an example project:
http://dl.dropbox.com/u/46508238/github.com/TestFody-2012-10-14.zip

The example above contains 2 projects, 7 classes and 3 unit tests (Test1 pass, Test2 and Test3 fail):

  • TestFody.csproj (Fody enabled)
    • UnitTest1.cs
    • ViewModel1.cs
    • ViewModel2.cs
    • ViewModel3.cs
  • ClassLibrary1.csproj (Fody not enabled)
    • BaseViewModel1.cs
    • BaseViewModel2.cs
    • BaseViewModel3.cs

[TestClass]
public class UnitTest1
{
    [TestMethod]
    public void Test1()
    {
        // Base class has OnPropertyChanged & OnPropertyChanging implemented.
        // Text property declared in sub class.
        Test(new ViewModel1()); // Pass
    }

    [TestMethod]
    public void Test2()
    {
        // Base class DOES NOT have OnPropertyChanged & OnPropertyChanging.
        // Text property declared in sub class.
        Test(new ViewModel2()); // Fail
    }

    [TestMethod]
    public void Test3()
    {
        // Base class has OnPropertyChanged & OnPropertyChanging implemented.
        // Text property declared in base class.
        Test(new ViewModel3()); // Fail
    }

    static void Test(dynamic vm)
    {
        bool isPropertyChangedFired = false;
        bool isPropertyChangingFired = false;

        (vm as INotifyPropertyChanged).PropertyChanged += 
            (sender, e) => isPropertyChangedFired = true;
        (vm as INotifyPropertyChanging).PropertyChanging += 
            (sender, e) => isPropertyChangingFired = true;

        vm.Text = string.Empty;

        Assert.IsTrue(isPropertyChangedFired);
        Assert.IsTrue(isPropertyChangingFired);
    }
}

public class ViewModel1 : BaseViewModel1
{
    public string Text { get; set; }
}

public class ViewModel2 : BaseViewModel2
{
    public string Text { get; set; }
}

public class ViewModel3 : BaseViewModel3
{
}

public class BaseViewModel1 : INotifyPropertyChanged, INotifyPropertyChanging
{
    public event PropertyChangedEventHandler PropertyChanged;
    public event PropertyChangingEventHandler PropertyChanging;

    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    protected void OnPropertyChanging(string propertyName)
    {
        if (PropertyChanging != null)
            PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
    }
}

public class BaseViewModel2 : INotifyPropertyChanged, INotifyPropertyChanging
{
    public event PropertyChangedEventHandler PropertyChanged;
    public event PropertyChangingEventHandler PropertyChanging;
}

public class BaseViewModel3 : INotifyPropertyChanged, INotifyPropertyChanging
{
    public string Text { get; set; }
    public event PropertyChangedEventHandler PropertyChanged;
    public event PropertyChangingEventHandler PropertyChanging;

    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    protected void OnPropertyChanging(string propertyName)
    {
        if (PropertyChanging != null)
            PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
    }
}
@SimonCropp
Copy link
Member

Unfortunately this is the expected behaviour

The reason is that from a child class you cant call the event on the base class. so there is no valid code I can inject into the child class to perform OnPropertyChanged or OnPropertyChanging. Since you dont have fody enabled for the project containing the base class I cant inject OnPropertyChanged in those classes.

This is why there is a warning

Warning 4   Fody/PropertyChanged.Fody:  Could not derive or inject 'OnPropertyChanged,    
NotifyOfPropertyChange, RaisePropertyChanged, NotifyPropertyChanged, NotifyChanged' into 'ViewModel2'. It is 
possible you are inheriting from a base class and have not correctly set 'EventInvokerNames' or you are using a 
explicit PropertyChanged event and the event field is not visible to this instance. Please either correct
'EventInvokerNames' or implement your own EventInvoker on this class. No derived types will be processed. If you
want to suppress this message place a [DoNotNotifyAttribute] on ViewModel2. TestFody

As for Text in BaseViewModel3 not being processed. Well you have not turned on fody for the project Fody has no visibility of it.

So... great repro but it is not something i can fix.

@yanglee
Copy link
Author

yanglee commented Oct 18, 2012

Ah, sorry didn't notice the warning message. Thanks for your detailed replay.

Cheers

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants