OnPropertyChanged не запускается, когда установлено свойство BindableProperty

#c# #xamarin #xamarin.forms

#c# #xamarin #xamarin.forms

Вопрос:

У меня возникли проблемы с настройкой BindableProperty IconName в пользовательском ContentView режиме в Xamarin.Формы. Он никогда не устанавливается и остается пустым. OnPropertyChanged Метод выполняется для каждого свойства, кроме IconName . Когда я меняю тип с enum на string , он работает так, как ожидалось. Чего мне не хватает?

OnPropertyChanged Метод необходим, иначе ни одно из свойств не будет установлено и останется значением по умолчанию..

 <?xml version="1.0" encoding="UTF-8" ?>
<ContentView
    x:Class="Peripass.Mobile.Framework.UIControls.PeripassIcon"
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:d="http://xamarin.com/schemas/2014/forms/design"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">
  <ContentView.Resources>
  </ContentView.Resources>
  <ContentView.Content>
    <StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
      <Image>
        <Image.Source>
          <FontImageSource x:Name="_icon" Glyph="" Color="Black" Size="20" FontFamily="{OnPlatform  Android=PeripassIcon.ttf#}" />
        </Image.Source>
      </Image>
    </StackLayout>
  </ContentView.Content>
</ContentView>
 
 using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace Peripass.Mobile.Framework.UIControls
{
  [XamlCompilation(XamlCompilationOptions.Compile)]
  public partial class PeripassIcon : ContentView
  {

    public static readonly BindableProperty IconSizeProperty = BindableProperty.Create(nameof(IconSize), typeof(double), typeof(PeripassIcon), 26.0);
    public static readonly BindableProperty IconColorProperty = BindableProperty.Create(nameof(IconColor), typeof(Color), typeof(PeripassIcon), Color.White);
    public static readonly BindableProperty IconNameProperty = BindableProperty.Create(nameof(IconName), typeof(IconType), typeof(PeripassIcon), IconType.NuclearExplosion);

    public PeripassIcon()
    {
      InitializeComponent();
    }

    public IconType IconName
    {
      get => (IconType)GetValue(IconNameProperty);
      set => SetValue(IconNameProperty, value);
    }

    public double IconSize
    {
      get => (double)GetValue(IconSizeProperty);
      set => SetValue(IconSizeProperty, value);
    }

    public Color IconColor
    {
      get => (Color)GetValue(IconColorProperty);
      set => SetValue(IconColorProperty, value);
    }

    protected override void OnPropertyChanged(string propertyName = null)
    {
      base.OnPropertyChanged(propertyName);
      if (propertyName == IconNameProperty.PropertyName) {
        _icon.Glyph = $"amp;#x{(int)IconName:X4};";
      }
      if (propertyName == IconColorProperty.PropertyName) {
        _icon.Color = IconColor;
      }
      if (propertyName == IconSizeProperty.PropertyName) {
        _icon.Size = IconSize;
      }
    }
  }
}
 
 <StackLayout Grid.Row="1" Grid.Column="0">
    <uiControls:PeripassIcon IconName="NuclearExplosion" IconColor="#EE4022" IconSize="85.5"/>
</StackLayout>
 

Ответ №1:

Проблема, с которой вы сталкиваетесь, связана с тем фактом, что OnPropertyChanged оно запускается только при изменении значения свойства (этого недостаточно для его установки!).).

В вашем коде вы устанавливаете значение по умолчанию IconName IconType.NuclearExplosion равным . Позже, когда вы вызываете установленный вами элемент управления

 <uiControls:PeripassIcon IconName="NuclearExplosion" IconColor="#EE4022" IconSize="85.5"/>
 

который снова устанавливает IconName значение по умолчанию… таким образом, его значение на самом деле не изменяется и, следовательно OnPropertyChanged , не запускается.


ПРЕДУПРЕЖДЕНИЕ

При этом я должен упомянуть, что «обычно» вы бы использовали привязки между свойствами BindableProperties и аналогами в представлении. Например, вы бы привязали значение свойства Color в FontImageSource в вашем contentView к значку BindableProperty IconColor . Подробности см. В Документации по contentView .

Комментарии:

1. @Tijl. Рейнхаут, я рад, что это помогло тебе. Я расширил ответ предупреждением. Пожалуйста, посмотрите и дайте мне знать, если это вам поможет…

2. Вы имеете в виду это в моем FontImageSource Color=»{Binding IconColor}», потому что это по какой-то причине не работает…

3. Если у вас есть сомнения в том, как это сделать, пожалуйста, задайте другой вопрос, и я буду рад взглянуть 🙂

4. Я создал еще один вопрос по этой теме 🙂