我为我的项目创建了控件层次结构:抽象 BaseSettingsElement
并继承了 EntrySettingsElement
、PickerSettingsElement
、SwitchSettingsElement
等. 基类提供更改标题/副标题的文本、颜色、字体的属性。属性声明示例:
public static readonly BindableProperty HeadTextColorProperty =
BindableProperty.Create("HeadTextColor", typeof(Color), typeof(BaseSettingsElement), Color.FromHex("#ffffff"),
propertyChanged: (bindable, oldValue, newValue) =>
{
(bindable as BaseSettingsElement).headText.TextColor = (Color)newValue;
});
//...
public Color HeadTextColor
{
get { return (Color)GetValue(HeadTextColorProperty); }
set { SetValue(HeadTextColorProperty, value); }
}
当我在 xaml 中创建这个控件并向它们应用一些属性时没有问题:
<custom:EntrySettingsElement Grid.Row="16"
InputType="Number"
DividersVisibility="None"
IsEnabled="False"
HeadTextColor="Red"
Text="0" />
但是当我尝试将 app.xaml 中的全局样式应用于我的某些控件时,我在此处遇到了 NullRefferenceException
:
public static readonly BindableProperty HeadTextColorProperty =
BindableProperty.Create("HeadTextColor", typeof(Color), typeof(BaseSettingsElement), Color.FromHex("#ffffff"),
propertyChanged: (bindable, oldValue, newValue) =>
{
(bindable as BaseSettingsElement).headText.TextColor = (Color)newValue;
//Here is a NullReferenceException: bindable object is not null but the field 'headText' is null...
});
以防万一基本控件的xaml:
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="RemoteControlApp.CustomViews.BaseSettingsElement"
xmlns:custom="clr-namespace:RemoteControlApp.CustomViews;assembly=RemoteControlApp">
<ContentView.Content>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<custom:Divider x:Name="topDivider"
Grid.Row="0"
Grid.ColumnSpan="2"
BackgroundColor="{StaticResource grayColor}" />
<StackLayout x:Name="container"
Orientation="Vertical"
Spacing="0"
Grid.Column="0"
Margin="15,12,0,12"
Grid.Row="1"
VerticalOptions="Center">
<Label x:Name="headText" />
<Label x:Name="bodyText" />
</StackLayout>
<custom:Divider x:Name="bottomDivider"
Grid.Row="2"
Grid.ColumnSpan="2"
BackgroundColor="{StaticResource grayColor}" />
<ContentView x:Name="asideContainer"
Margin="0,0,15,0"
Grid.Column="1"
Grid.Row="1" />
</Grid>
</ContentView.Content>
</ContentView>
最佳答案
快速查看编译器生成的文件 (.xaml.g.cs) - 您会注意到这些私有(private)字段是在 InitializeComponent
方法中分配的:
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Forms.Build.Tasks.XamlG", "0.0.0.0")]
private void InitializeComponent()
{
global::Xamarin.Forms.Xaml.Extensions.LoadFromXaml(this, typeof(BaseSettingsElement));
headText = global::Xamarin.Forms.NameScopeExtensions.FindByName<global::Xamarin.Forms.Label>(this, "headText");
}
因此,这似乎是由于InitializeComponent
和PropertyChangedHandler
的调用顺序导致的问题。
在第一种情况下,当显式设置属性时,这是调用方法的顺序。
InitializeComponent -Start
InitializeComponent -End
HeadTextColor -PropertyChanged
而第二种情况,使用全局样式设置属性时,顺序是:
HeadTextColor -PropertyChanged
InitializeComponent -Start
InitializeComponent -End
看起来该属性是在基类构造函数中的某处设置的。所以 NullReferenceException
是预期的。
有两种方法可以解决这个问题。
方案一(推荐)
不使用属性更改处理程序,而是使用 Binding
来设置内部子控件的属性,父节点作为 Source
。例如:
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="RemoteControlApp.CustomViews.BaseSettingsElement"
xmlns:custom="clr-namespace:RemoteControlApp.CustomViews;assembly=RemoteControlApp"
x:Name="_parent">
<ContentView.Content>
<!-- .... -->
<Label TextColor="{Binding HeadTextColor, Source={x:Reference _parent}}" />
方案二
或者,在InitializeComponent
之后设置内部控件的属性。
public MyView()
{
Debug.WriteLine("InitializeComponent -Start");
InitializeComponent();
Debug.WriteLine("InitializeComponent -End");
//InitializeControl();
this.headText.TextColor = HeadTextColor;
}
注意:在第二种解决方案中,您仍然需要属性更改处理程序。否则,在 XAML 中显式设置属性不会将更改传播到内部控件。我想为此需要进行空检查。
关于c# - 当我尝试将全局样式应用于 Xamarin Forms 中的自定义 ContentView 时出现 NullReferenceException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46142251/