.Net MAUI Styles.xaml 未检测 Visual Studio 中的自定义控件属性(XFC0001)

问题描述 投票:0回答:1

当我在整个项目中创建自定义控件时,我意识到我需要通过

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)".

因此,无论出于何种原因,编译器似乎都无法检测到任何自定义属性。

c# .net xaml maui
1个回答
0
投票

可绑定属性必须是

static
,例如,

  public static readonly BindableProperty StyleTitleProperty = BindableProperty.Create(nameof(StyleTitle), typeof(Style), typeof(LoadingView));
© www.soinside.com 2019 - 2024. All rights reserved.