在自定义视图上设置可绑定属性时,ListDictionaryInternal上的空引用异常

Sev*_*Sev 5 c# data-binding xaml xamarin.forms .net-standard-2.0

我刚刚将我的Xamarin Forms项目迁移到.NET Standard 2.0,并且正在与一些奇怪的行为作斗争.在下面的情况中,我在ListDictionaryInternal上得到一个Null引用异常,没有异常断点,没有堆栈跟踪,也没有其他可用信息.情况是,从我的视图模型我在自定义按钮控件上设置可绑定文本属性.我已经在文本设置过程中一直调试,之后发生异常.我完全被这一个难住了.需要明确的是,此代码在.NET Standard 2.0迁移之前正在运行.先感谢您!

更新:

所以这个异常已经开始发生在Forms iOS上,但现在我能够在System.Exception断点点击时获得堆栈跟踪.这也与.NET Standard 2.0无关,因为在定位PCL 4.5项目时,也会发生这种情况.

我可以在OnSizeAllocated覆盖方法后面的代码中设置断点,并看到视图已接受绑定文本并正确布局.因此,问题不是绑定,而是布局视图.

此外,为了澄清,只有在使用可绑定属性设置文本时才会发生此异常.如果在xaml中设置了文本,则不会发生异常.

在此输入图像描述

ViewModel ......

public class SimpleSearchViewModel : BaseViewModel
{
    enum SearchCatagories
    {
        All,
        SubjectId,
        PublicationNumber
    }

    public override void OnStart()
    {
        UpdateTypeButton("ALL");
    }

    private void UpdateTypeButton(string item)
    {
        SearchTypeButtonText = item;
    }

    private string _searchTypeButtonText;
    public string SearchTypeButtonText
    {
        get
        {
            return _searchTypeButtonText;
        }
        private set
        {
            _searchTypeButtonText = value;
            OnPropertyChanged(nameof(SearchTypeButtonText));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

风景...

<core:BasePage xmlns="http://xamarin.com/schemas/2014/forms" 
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
xmlns:viewmodels="using:App.ViewModels"
xmlns:customcontrols="clr-namespace:App;assembly=App"
xmlns:core="clr-namespace:App.Core;assembly=App.Core"
x:Class="Pages.SimpleSearchPage"
Title="Simple Search">

<ContentPage.BindingContext>
    <viewmodels:SimpleSearchViewModel />
</ContentPage.BindingContext>

<ContentPage.Content>

<StackLayout Padding=" 10, 10, 10, 10" 
             HorizontalOptions="FillAndExpand" 
             VerticalOptions="FillAndExpand" 
             Orientation="Horizontal" > 

            <customcontrols:SVGImageButton x:Name="TypeSelectionButton" 
                            HorizontalOptions="Start" 
                            VerticalOptions="Center"
                            ButtonPressedCommand="{Binding TypeButtonClickedCommand}"
                               SVGImageName="SVGImages.ic_triangle_down.svg"
                            CommandParameter="{x:Reference TypeSelectionButton}"
                            ButtonText="{Binding SearchTypeButtonText}"
                            ButtonBackgroundColor="{Binding ButtonBackgroundColor}"/>

        </StackLayout>
    </ContentPage.Content>
</core:BasePage>
Run Code Online (Sandbox Code Playgroud)

SVGImageButton ......

[XamlCompilation(XamlCompilationOptions.Compile)]
public class SVGImageButton : ContentView
{
    private readonly Button _button;
    private readonly SvgCachedImage _svgImage;

    public static BindableProperty ButtonTextProperty =    BindableProperty.Create(nameof(ButtonText), typeof(string),   typeof(SVGImageButton), string.Empty, BindingMode.OneWay, propertyChanged: (bindable, oldValue, newValue) =>
    {
        if (newValue == null) return;
        var control = (SVGImageButton)bindable;
        control.ButtonText = newValue.ToString();
    });

    public string ButtonText
    {
        get
        {
            return _button.Text;
        }
        set
        {
            _button.Text = value; 
        }
    }

    public string SVGImageName { get; set; }

    protected override void OnParentSet()
    {
        base.OnParentSet();

        _button.Text = ButtonText;
        _svgImage.Source = SvgImageSource.FromResource(SVGImageName);
     }

    public SVGImageButton()
    {
        var content = new RelativeLayout();

        _button = new Button { BackgroundColor = Color.Gray, TextColor = Color.Black };
        _svgImage = new SvgCachedImage { IsEnabled = false };

        content.Children.Add(_button,
                             Constraint.RelativeToParent((parent) =>
                             {
                                 return parent.X;
                             }),
                             Constraint.RelativeToParent((parent) =>
                             {
                                 return parent.Y;
                             }),
                             Constraint.RelativeToParent((parent) =>
                             {
                                 return parent.Width;
                             }),
                             Constraint.RelativeToParent((parent) =>
                             {
                                 return parent.Height;
                             }));

        content.Children.Add(_svgImage,
                           Constraint.RelativeToParent((parent) =>
                           {
                               return parent.Width - (parent.Height / 2) - (parent.Height / 4);
                           }),
                           Constraint.RelativeToParent((parent) =>
                           {
                               return parent.Height - (parent.Height /     2) - (parent.Height / 4);
                           }),
                           Constraint.RelativeToParent((parent) =>
                           {
                               return parent.Height / 2;
                           }),
                           Constraint.RelativeToParent((parent) =>
                           {
                               return parent.Height / 2;
                           }));

        Content = content;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

Sev*_*Sev 0

所以这个问题最终来自于我在 OnMeasure 回调中处理控件大小的方式。正确的问题和答案可以在这里看到。