在自定义视图上设置可绑定 属性 时,ListDictionaryInternal 出现空引用异常
Null reference exception on a ListDictionaryInternal when setting bindable property on custom view
我刚刚将我的 Xamarin Forms 项目迁移到 .NET Standard 2.0,并且遇到了一些奇怪的行为。在以下情况下,我在 ListDictionaryInternal 上收到空引用异常,没有异常断点,没有堆栈跟踪,也没有其他可用信息。情况是,从我的视图模型中,我在自定义按钮控件上设置了可绑定文本 属性。我已经调试了整个文本设置过程,之后发生了异常。我完全被这个难住了。需要明确的是,此代码在 .NET Standard 2.0 迁移之前有效。提前致谢!
更新:
所以这个异常也开始在 Forms iOS 中发生,但现在我能够在 System.Exception 断点命中时获得堆栈跟踪。此外,这与 .NET Standard 2.0 无关,因为在针对 PCL 4.5 项目时也会发生这种情况,确切地说是配置文件 111。
我可以在 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));
}
}
}
风景...
<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>
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;
}
}
}
所以这个问题最终来自于我在 OnMeasure 回调中处理控件大小的方式。正确的问题和答案可见.
我刚刚将我的 Xamarin Forms 项目迁移到 .NET Standard 2.0,并且遇到了一些奇怪的行为。在以下情况下,我在 ListDictionaryInternal 上收到空引用异常,没有异常断点,没有堆栈跟踪,也没有其他可用信息。情况是,从我的视图模型中,我在自定义按钮控件上设置了可绑定文本 属性。我已经调试了整个文本设置过程,之后发生了异常。我完全被这个难住了。需要明确的是,此代码在 .NET Standard 2.0 迁移之前有效。提前致谢!
更新:
所以这个异常也开始在 Forms iOS 中发生,但现在我能够在 System.Exception 断点命中时获得堆栈跟踪。此外,这与 .NET Standard 2.0 无关,因为在针对 PCL 4.5 项目时也会发生这种情况,确切地说是配置文件 111。
我可以在 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));
}
}
}
风景...
<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>
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;
}
}
}
所以这个问题最终来自于我在 OnMeasure 回调中处理控件大小的方式。正确的问题和答案可见