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

[XF] EventToCommandBehavior.OnEventRaised NullReferenceException #1549

Closed
chowarth opened this issue Sep 19, 2018 · 4 comments
Closed

[XF] EventToCommandBehavior.OnEventRaised NullReferenceException #1549

chowarth opened this issue Sep 19, 2018 · 4 comments

Comments

@chowarth
Copy link
Contributor

Description

Setting EventArgsParameterPath to a property that is declared in a derived class of the event arguments causes a NullReferenceException to be thrown.

e.g. WebView.Navigating event arguments WebNavigatingEventArgs derives from WebNavigationEventArgs. The Url property is declared within WebNavigatingEventArgs so when you set EventArgsParameterPath to Url it will cause a NullReferenceException to be thrown.

Steps to Reproduce

Best reproduced on iOS as the Navigating event doesn't fire on an initial page load for Android.

  1. Create a new Prism Blank App
  2. Replace MainPage with the following:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:b="clr-namespace:Prism.Behaviors;assembly=Prism.Forms"
             x:Class="EventToCommandBehavior.Views.MainPage"
             Title="{Binding Title}">

    <WebView
        Source="{Binding Url}">
        <WebView.Behaviors>
            <b:EventToCommandBehavior
                EventName="Navigating"
                EventArgsParameterPath="Url"
                Command="{Binding NavigatingCommand}"/>
        </WebView.Behaviors>
    </WebView>

</ContentPage>
  1. Replace MainPageViewModel with the following:
    public class MainPageViewModel : ViewModelBase
    {
        public DelegateCommand<string> NavigatingCommand { get; }

        public string Url
        {
            get => "https://prismlibrary.github.io";
        }

        public MainPageViewModel(INavigationService navigationService)
            : base(navigationService)
        {
            Title = "Main Page";

            NavigatingCommand = new DelegateCommand<string>(OnNavigating);
        }

        private void OnNavigating(string url)
        {
            Console.WriteLine($"[URL]:{url}");
        }
    }

Reproduction Link

EventToCommandBehavior.zip

Expected Behavior

Bound command is executed with the Url parameter

Actual Behavior

NullReferenceException is thrown

Basic Information

  • Version with issue: Prism.Forms 7.0.0.396
  • Last known good version: -
  • Xamarin.Forms version: 2.5.0.122203
  • IDE: Visual Studio 2017 (15.8.4)

Suggested Fix

Change:

var propInfo = propertyValue.GetType().GetTypeInfo().GetDeclaredProperty(propertyPathPart);

To:

var propInfo = propertyValue.GetType().GetProperty(propertyPathPart);
@brianlagunas
Copy link
Member

Thank you for reporting this. unfortunately GetProperty is not available in NetStandard 1.0. We will need to determine another fix, or just recommend using a converter in NetStandard 1.0 and fix it for 2.0.

We could use GetRuntimeProperty, but that also gets non-public values, which may also cause issues and a possible perf hit (not tested just assumed).

@brianlagunas
Copy link
Member

We went with the GetRuntimeProperty approach. Test it out in the latest CI build on MyGet and let us know if you are still having issues.

@chowarth
Copy link
Contributor Author

chowarth commented Sep 20, 2018

Sounds good and I'll give it a whirl later today when I get chance. Didn't expect you to put a fix in so quickly haha.

While GetProperty is not available in NetStandard 1.0 Xamarin.Forms has its own internal extension method, see here and here, which is what I used along with the test below to confirm that everything worked OK.

[Fact]
public void Command_EventArgsParameterPath_BaseDeclaredProperty()
{
    var executedCommand = false;
    var behavior = new EventToCommandBehaviorMock
    {
        EventName = "Navigating",
        EventArgsParameterPath = "Url", // Url is declared in WebNavigationEventArgs, not WebNavigatingEventArgs
        Command = new DelegateCommand<string>(o =>
        {
            executedCommand = true;
            Assert.NotNull(o);
        })
    };
    var webView = new WebView();
    webView.Behaviors.Add(behavior);
    behavior.RaiseEvent(webView, new WebNavigatingEventArgs(new WebNavigationEvent(), null, "http://prismlibrary.github.io/"));
    Assert.True(executedCommand);
}

@lock
Copy link

lock bot commented Jan 29, 2020

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

@lock lock bot locked as resolved and limited conversation to collaborators Jan 29, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants