C# 在Xamarin Forms Framework中导致空引用异常的自定义控件

C# 在Xamarin Forms Framework中导致空引用异常的自定义控件,c#,svg,xamarin.forms,custom-controls,nullreferenceexception,C#,Svg,Xamarin.forms,Custom Controls,Nullreferenceexception,我构建了一个自定义SVG按钮,这样我就可以拥有一个带有文本和SVG图像的Xamarin表单按钮。我已经让它运行良好,然后我将我的项目迁移到.NET标准2.0 现在,当更改控件上的文本时,我在ListDictionaryInternal上的Xamarin Forms框架的StackLayout的LayoutChildIntoBoundingRegion方法中得到一个空引用异常 这是控制按钮。这很简单 using System.Windows.Input; using FFImageLoading.

我构建了一个自定义SVG按钮,这样我就可以拥有一个带有文本和SVG图像的Xamarin表单按钮。我已经让它运行良好,然后我将我的项目迁移到.NET标准2.0

现在,当更改控件上的文本时,我在ListDictionaryInternal上的Xamarin Forms框架的StackLayout的LayoutChildIntoBoundingRegion方法中得到一个空引用异常

这是控制按钮。这很简单

using System.Windows.Input;
using FFImageLoading.Svg.Forms;
using Core.Interfaceses;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace CustomControls
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public class SVGImageButton : ContentView
    {
        #region Member Variables

        private readonly Button _button;
        private readonly SvgCachedImage _svgImage;

        #endregion

        #region Bindible Properties

        public static BindableProperty ButtonPressedCommandProperty = BindableProperty.Create(nameof(ButtonPressedCommand), typeof(ICommand), typeof(SVGImageButton));
        public ICommand ButtonPressedCommand
        {
            get
            {
                return (ICommand)GetValue(ButtonPressedCommandProperty);
            }
            set
            {
                SetValue(ButtonPressedCommandProperty, value);
            }
        }

        public static BindableProperty CommandParameterProperty = BindableProperty.Create(nameof(CommandParameter), typeof(object), typeof(SVGImageButton));
        public object CommandParameter
        {
            get { return GetValue(CommandParameterProperty); }
            set { SetValue(CommandParameterProperty, value); }
        }

        public static BindableProperty ButtonTextProperty = BindableProperty.Create(nameof(ButtonText), typeof(string), typeof(SVGImageButton), string.Empty, BindingMode.TwoWay, 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 static BindableProperty ButtonBackgroundColorProperty = BindableProperty.Create(nameof(ButtonBackgroundColor), typeof(Color), typeof(View), Color.Fuchsia, BindingMode.OneWay, propertyChanged: (bindable, oldValue, newValue) =>
        {
            if (newValue == null) return;
            var control = (SVGImageButton)bindable;
            control.ButtonBackgroundColor = (Color)newValue;
        });

        public Color ButtonBackgroundColor
        {
            get
            {
                return _button.BackgroundColor;
            }
            set
            {
                _button.BackgroundColor = value;
            }
        }

        public static BindableProperty ButtonTextColorProperty = BindableProperty.Create(nameof(ButtonTextColor), typeof(Color), typeof(View), Color.Fuchsia, BindingMode.OneWay, propertyChanged: (bindable, oldValue, newValue) =>
        {
            if (newValue == null) return;
            var control = (SVGImageButton)bindable;
            control.ButtonTextColor = (Color)newValue;
        });

        public Color ButtonTextColor
        {
            get
            {
                return _button.TextColor;
            }
            set
            {
                _button.TextColor = value;
            }
        }

        public static BindableProperty ButtonStyleProperty = BindableProperty.Create(nameof(ButtonBackgroundColor), typeof(Style), typeof(View), null, BindingMode.OneWay, propertyChanged: (bindable, oldValue, newValue) =>
        {
            if (newValue == null) return;
            var control = (SVGImageButton)bindable;
            control.ButtonStyle = (Style)newValue;
        });

        public Style ButtonStyle
        {
            get
            {
                return _button.Style;
            }
            set
            {
                _button.Style = value;
            }
        }

        public static BindableProperty ButtonBorderWidthProperty = BindableProperty.Create(nameof(ButtonBorderWidth), typeof(double), typeof(View), 0.0, BindingMode.OneWay, propertyChanged: (bindable, oldValue, newValue) =>
        {
            if (newValue == null) return;
            var control = (SVGImageButton)bindable;
            control.ButtonBorderWidth = (double)newValue;
        });

        public double ButtonBorderWidth
        {
            get
            {
                return _button.BorderWidth;
            }
            set
            {
                _button.BorderWidth = value;
            }
        }

        public static BindableProperty ButtonBorderColorProperty = BindableProperty.Create(nameof(ButtonBorderColor), typeof(Color), typeof(View), Color.Fuchsia, BindingMode.OneWay, propertyChanged: (bindable, oldValue, newValue) =>
        {
            if (newValue == null) return;
            var control = (SVGImageButton)bindable;
            control.ButtonBorderColor = (Color)newValue;
        });

        public Color ButtonBorderColor
        {
            get
            {
                return _button.BorderColor;
            }
            set
            {
                _button.BorderColor = value;
            }
        }

        #endregion

        #region Properties

        public string SVGImageName { get; set; }

        #endregion

        #region Life Cycle

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

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

        protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
        {
            _button.HorizontalOptions = (Parent as View).HorizontalOptions;
            _button.VerticalOptions = (Parent as View).VerticalOptions;

            if (_button.Text != null)
            {
                var size = DependencyService.Get<ITextMeter>().MeasureTextSize(_button.Text.TrimEnd(), 200, _button.FontSize);
                WidthRequest = size.Width + 60 + _button.Height;
            }

            return base.OnMeasure(widthConstraint, heightConstraint);
        }

        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;

            _button.Clicked += (sender, e) =>
            {
                ButtonPressedCommand?.Execute(CommandParameter);
            };
        }

        #endregion

    }
}
使用System.Windows.Input;
使用ffimageload.Svg.Forms;
使用核心接口;
使用Xamarin.Forms;
使用Xamarin.Forms.Xaml;
命名空间自定义控件
{
[XamlCompilation(XamlCompilationOptions.Compile)]
公共类SVGImageButton:ContentView
{
#区域成员变量
专用只读按钮_按钮;
私有只读SvgCachedImage _svgImage;
#端区
#区域可结合性质
public static BindableProperty ButtonPressedCommandProperty=BindableProperty.Create(nameof(ButtonPressedCommand)、typeof(ICommand)、typeof(SVGImageButton));
公用图标命令按钮按下命令
{
得到
{
返回(ICommand)GetValue(按钮PressedCommand属性);
}
设置
{
SetValue(按钮PressedCommand属性,值);
}
}
public static BindableProperty CommandParameterProperty=BindableProperty.Create(nameof(CommandParameter)、typeof(object)、typeof(SVGImageButton));
公共对象命令参数
{
获取{return GetValue(CommandParameterProperty);}
set{SetValue(CommandParameterProperty,value);}
}
public static BindableProperty buttonextproperty=BindableProperty.Create(nameof(buttonext)、typeof(string)、typeof(SVGImageButton)、string.Empty、BindingMode.TwoWay、propertyChanged:(bindable、oldValue、newValue)=>
{
if(newValue==null)返回;
var control=(SVGImageButton)可绑定;
control.ButtonText=newValue.ToString();
});
公共字符串按钮文本
{
得到
{
返回_button.Text;
}
设置
{
_文本=值;
}
}
公共静态BindableProperty ButtonBackgroundColorProperty=BindableProperty.Create(名称)(ButtonBackgroundColor)、类型(颜色)、类型(视图)、颜色.Fuchsia、BindingMode.OneWay、属性更改:(bindable、oldValue、newValue)=>
{
if(newValue==null)返回;
var control=(SVGImageButton)可绑定;
control.ButtonBackgroundColor=(Color)newValue;
});
公共颜色按钮背景颜色
{
得到
{
返回按钮。背景颜色;
}
设置
{
_button.BackgroundColor=值;
}
}
公共静态BindableProperty ButtonExtColorProperty=BindableProperty.Create(名称)(ButtonExtColor)、typeof(颜色)、typeof(视图)、Color.Fuchsia、BindingMode.OneWay、propertyChanged:(bindable、oldValue、newValue)=>
{
if(newValue==null)返回;
var control=(SVGImageButton)可绑定;
control.buttonextcolor=(Color)newValue;
});
公共颜色按钮ExtColor
{
得到
{
返回_button.TextColor;
}
设置
{
_button.TextColor=值;
}
}
public static BindableProperty ButtonStyleProperty=BindableProperty.Create(nameof(ButtonBackgroundColor)、typeof(Style)、typeof(View)、null、BindingMode.OneWay、propertyChanged:(bindable、oldValue、newValue)=>
{
if(newValue==null)返回;
var control=(SVGImageButton)可绑定;
control.ButtonStyle=(Style)newValue;
});
公共样式按钮样式
{
得到
{
返回按钮样式;
}
设置
{
_样式=值;
}
}
公共静态BindableProperty ButtonOrderWidthProperty=BindableProperty.Create(nameof(ButtonOrderWidth)、typeof(double)、typeof(View)、0.0、BindingMode.OneWay、propertyChanged:(bindable、oldValue、newValue)=>
{
if(newValue==null)返回;
var control=(SVGImageButton)可绑定;
control.ButtonOrderWidth=(双精度)newValue;
});
公共双按钮宽度
{
得到
{
返回按钮。边框宽度;
}
设置
{
_button.BorderWidth=值;
}
}
公共静态BindableProperty ButtonOrderColorProperty=BindableProperty.Create(nameof(ButtonOrderColor)、typeof(Color)、typeof(View)、Color.Fuchsia、BindingMode.OneWay、propertyChanged:(bindable、oldValue、newValue)=>
{
if(newValue==null)返回;
var control=(SVGImageButton)可绑定;
control.ButtonOrderColor=(颜色)newValue;
});
公共颜色按钮顺序颜色
{
得到
{
返回按钮。边框颜色;
}
设置
{
_button.BorderColor=值;
}
}
#端区
#区域属性
公共字符串SVGImageName{get;set;}
#端区
#区域生命周期
受保护的覆盖无效OnParentSet()
{
base.OnParentSet();
_button.Text=ButtonText;
_svgImage.Source=SvgImageSource.FromResource(SVGImageName);
}
测量时受保护的覆盖尺寸请求(双宽度约束、双高度约束)
<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}"/>
protected override SizeRequest OnMeasure(double widthConstraint, double heightConstraint)
{
    _button.HorizontalOptions = (Parent as View).HorizontalOptions;
    _button.VerticalOptions = (Parent as View).VerticalOptions;

    var width = 0d;
    if (_button.Text != null)
    {
        var size = DependencyService.Get<ITextMeter>().MeasureTextSize(_button.Text.TrimEnd(), 200, _button.FontSize);
        width = size.Width + 40 + _button.Height;
    }

    return base.OnMeasure(width, heightConstraint);
}