当我在整个项目中创建自定义控件时,我意识到我需要通过
Styles.xaml
文件来设置它们的样式。为此,我显然必须将所有控件的属性转换为 BindableProperties
。我用我的一个自定义控件 CameraView.xaml
做到了这一点,并且效果很好。
之后,我对另一个控件
LoadingView.xaml
做了同样的事情,按照相同的步骤将所有属性转换为可绑定属性。一切都很顺利,直到我想为其创建一种样式。
显然,
Styles.xaml
文件无法识别控件的任何自定义属性。我真的不知道为什么,因为我遵循了与第一个控件完全相同的步骤。值得注意的是,它识别了 ContentView
的所有标准属性,但没有识别我所做的属性。
我花了很多时间试图理解为什么它不起作用,但目前还没有结果。我也尝试过修改一些属性、重建整个解决方案、关闭和打开 VisualStudio 等等,但都没有效果。
所以我想问一下:我写的属性有问题吗?数量相当多,我提前道歉,但此时我真的不知道该怎么办。
正在加载View.xaml.cs:
(...)
/// <summary>
/// Gets or sets the title's style.
/// </summary>
public Style StyleTitle
{
set => SetValue(StyleTitleProperty, value);
get => (Style)GetValue(StyleTitleProperty);
}
/// <summary>
/// StyleTitle bindable property.
/// </summary>
public readonly BindableProperty StyleTitleProperty = BindableProperty.Create(nameof(StyleTitle), typeof(Style), typeof(LoadingView));
/// <summary>
/// Gets or sets the text's style.
/// </summary>
public Style StyleText
{
set => SetValue(StyleTextProperty, value);
get => (Style)GetValue(StyleTextProperty);
}
/// <summary>
/// StyleText bindable property.
/// </summary>
public readonly BindableProperty StyleTextProperty = BindableProperty.Create(nameof(StyleText), typeof(Style), typeof(LoadingView));
/// <summary>
/// Gets or sets the retry button's style.
/// </summary>
public Style StyleButton
{
set => SetValue(StyleButtonProperty, value);
get => (Style)GetValue(StyleButtonProperty);
}
/// <summary>
/// StyleButton bindable property.
/// </summary>
public readonly BindableProperty StyleButtonProperty = BindableProperty.Create(nameof(StyleButton), typeof(Style), typeof(LoadingView));
/// <summary>
/// Gets or sets the current lottie source.
/// </summary>
public SKLottieImageSource? LottieSource
{
set => SetValue(LottieSourceProperty, value);
get => GetValue(LottieSourceProperty) as SKLottieImageSource;
}
/// <summary>
/// LottieSource bindable property.
/// </summary>
public readonly BindableProperty LottieSourceProperty = BindableProperty.Create(nameof(LottieSource), typeof(SKLottieImageSource), typeof(LoadingView));
/// <summary>
/// Gets or sets the image source for when the view is loading.
/// </summary>
public SKLottieImageSource? LoadingLottieSource
{
set => SetValue(LoadingLottieSourceProperty, value);
get => GetValue(LoadingLottieSourceProperty) as SKLottieImageSource;
}
/// <summary>
/// LoadingLottieSource bindable property.
/// </summary>
public readonly BindableProperty LoadingLottieSourceProperty = BindableProperty.Create(nameof(LoadingLottieSource), typeof(SKLottieImageSource), typeof(LoadingView));
/// <summary>
/// Gets or sets the image source for when an exception is thrown while loading.
/// </summary>
public SKLottieImageSource? ErrorLottieSource
{
set => SetValue(ErrorLottieSourceProperty, value);
get => GetValue(ErrorLottieSourceProperty) as SKLottieImageSource;
}
/// <summary>
/// ErrorLottieSource bindable property.
/// </summary>
public readonly BindableProperty ErrorLottieSourceProperty = BindableProperty.Create(nameof(ErrorLottieSource), typeof(SKLottieImageSource), typeof(LoadingView));
/// <summary>
/// Gets or sets the view's title.
/// </summary>
public string? Title
{
set => SetValue(TitleProperty, value);
get => GetValue(TitleProperty) as string;
}
/// <summary>
/// Title bindable property.
/// </summary>
public readonly BindableProperty TitleProperty = BindableProperty.Create(nameof(Title), typeof(string), typeof(LoadingView));
/// <summary>
/// Gets or sets the view's text.
/// </summary>
public string? Text
{
set => SetValue(TextProperty, value);
get => GetValue(TextProperty) as string;
}
/// <summary>
/// Text bindable property.
/// </summary>
public readonly BindableProperty TextProperty = BindableProperty.Create(nameof(Text), typeof(string), typeof(LoadingView));
/// <summary>
/// Gets or sets the title for when the view is loading.
/// </summary>
public string? LoadingTitle
{
set => SetValue(LoadingTitleProperty, value);
get => GetValue(LoadingTitleProperty) as string;
}
/// <summary>
/// LoadingTitle bindable property.
/// </summary>
public readonly BindableProperty LoadingTitleProperty = BindableProperty.Create(nameof(LoadingTitle), typeof(string), typeof(LoadingView));
/// <summary>
/// Gets or sets the text for when the view is loading.
/// </summary>
public string? LoadingText
{
set => SetValue(LoadingTextProperty, value);
get => GetValue(LoadingTextProperty) as string;
}
/// <summary>
/// LoadingText bindable property.
/// </summary>
public readonly BindableProperty LoadingTextProperty = BindableProperty.Create(nameof(LoadingText), typeof(string), typeof(LoadingView));
/// <summary>
/// Gets or sets the title for when the view throws an exception.
/// </summary>
public string? ErrorTitle
{
set => SetValue(ErrorTitleProperty, value);
get => GetValue(ErrorTitleProperty) as string;
}
/// <summary>
/// ErrorTitle bindable property.
/// </summary>
public readonly BindableProperty ErrorTitleProperty = BindableProperty.Create(nameof(ErrorTitle), typeof(string), typeof(LoadingView));
/// <summary>
/// Gets or sets the text for when the view throws an exception. Can use string.Format with the following indexes:
/// 0: The exception type;
/// 1: The exception message.
/// </summary>
public string? ErrorText
{
set => SetValue(ErrorTextProperty, value);
get => GetValue(ErrorTextProperty) as string;
}
/// <summary>
/// ErrorText bindable property.
/// </summary>
public readonly BindableProperty ErrorTextProperty = BindableProperty.Create(nameof(ErrorText), typeof(string), typeof(LoadingView));
/// <summary>
/// Gets or sets the retry button's text.
/// </summary>
public string? ButtonText
{
set => SetValue(ButtonTextProperty, value);
get => GetValue(ButtonTextProperty) as string;
}
/// <summary>
/// ButtonText bindable property.
/// </summary>
public readonly BindableProperty ButtonTextProperty = BindableProperty.Create(nameof(ButtonText), typeof(string), typeof(LoadingView));
/// <summary>
/// Gets or sets the lottie's repeat count.
/// </summary>
public int LottieRepeat
{
set => SetValue(LottieRepeatProperty, value);
get => (int)GetValue(LottieRepeatProperty);
}
/// <summary>
/// LottieRepeat bindable property.
/// </summary>
public readonly BindableProperty LottieRepeatProperty = BindableProperty.Create(nameof(LottieRepeat), typeof(int), typeof(LoadingView));
/// <summary>
/// Number of times that the loading lottie has to repeat.
/// </summary>
public int LoadingLottieRepeat
{
set => SetValue(LoadingLottieRepeatProperty, value);
get => (int)GetValue(LoadingLottieRepeatProperty);
}
/// <summary>
/// LoadingLottieRepeat bindable property.
/// </summary>
public readonly BindableProperty LoadingLottieRepeatProperty = BindableProperty.Create(nameof(LoadingLottieRepeat), typeof(int), typeof(LoadingView));
(...)
正在加载View.xaml:
<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:skia="clr-namespace:SkiaSharp.Extended.UI.Controls;assembly=SkiaSharp.Extended.UI"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Cephei.MAUI.Lottie.LoadingView">
<VerticalStackLayout>
<skia:SKLottieView x:Name="LottieView" WidthRequest="200" HeightRequest="200" Source="{Binding LottieSource}" RepeatCount="{Binding LottieRepeat}"/>
<Label x:Name="LabelTitle" Style="{Binding StyleTitle}" Text="{Binding Title}"/>
<Label x:Name="LabelDetail" Style="{Binding StyleText}" Text="{Binding Text}"/>
<Button x:Name="ButtonRetry" Style="{Binding StyleButton}" Text="{Binding ButtonText}" IsVisible="False" Clicked="Button_Clicked"/>
</VerticalStackLayout>
</ContentView>
样式.xaml:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:lottie="clr-namespace:Cephei.MAUI.Lottie;assembly=Cephei.MAUI.Lottie"
xmlns:camera="clr-namespace:Cephei.MAUI.Camera;assembly=Cephei.MAUI.Camera"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
(...)
<Style TargetType="camera:CameraView">
<!-- The CameraView's properties worked just fine -->
<Setter Property="CameraWidth" Value="300"/>
<Setter Property="CameraHeight" Value="300"/>
<Setter Property="OverlayWidth" Value="275"/>
<Setter Property="OverlayHeight" Value="275"/>
<Setter Property="OverlayCornerWidth" Value="8"/>
<Setter Property="OverlayCornerHeight" Value="8"/>
<Setter Property="OverlayCornerThickness" Value="2"/>
</Style>
<Style TargetType="lottie:LoadingView">
<!-- None of the LoadingView's custom properties are appearing as suggestions in Visual Studio -->
</Style>
(...)
任何可以帮助我解决这个问题的帮助将不胜感激。预先感谢!
编辑:即使我将自定义属性强制到控件的样式上,编译器也会引发以下异常:
XFC0001: Cannot resolve property "LoadingTitle" on type "LoadingView (property missing or missing accessors)".
因此,无论出于何种原因,编译器似乎都无法检测到任何自定义属性。
可绑定属性必须是
static
,例如,
public static readonly BindableProperty StyleTitleProperty = BindableProperty.Create(nameof(StyleTitle), typeof(Style), typeof(LoadingView));