Свойство BindableProperty пользовательского элемента управления Xamarin FormsChanged not Firing - PullRequest
0 голосов
/ 01 октября 2019

Попытка настроить очень простой пользовательский элемент управления для обработки выравнивания при использовании маркеров в метке. Проблема заключается в том, что диапазоны, переданные в пользовательский элемент управления, не распознаются, а содержимое не обрабатывается (и функция propertyChanged не запускается). Чего мне не хватает?

XAML:

<?xml version="1.0" encoding="UTF-8" ?>
<ContentView
    x:Class="Sample.Controls.BulletPointItem"
    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.Content>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="10" />
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
            <Label x:Name="BulletPoint" Text="&#x2022;" />
            <Label x:Name="LabelContent" Grid.Column="1" />
        </Grid>
    </ContentView.Content>
</ContentView>

Кодовый код:

[ContentProperty(nameof(Spans))]
public partial class BulletPointItem : ContentView
{
    // todo add bindable props for bullet point size and color, or even which character to use as the bullet point!
    public static readonly BindableProperty SpansProperty =
        BindableProperty.Create(
            nameof(Spans),
            typeof(ObservableCollection<Span>),
            typeof(BulletPointItem),
            new ObservableCollection<Span>(),
            BindingMode.OneWay,
            propertyChanged: OnSpansChanged);

    public BulletPointItem()
    {
        InitializeComponent();
    }

    public ObservableCollection<Span> Spans
    {
        get => (ObservableCollection<Span>)GetValue(SpansProperty);
        set => SetValue(SpansProperty, value);
    }

    private static void OnSpansChanged(BindableObject bindable, object oldValue, object newValue)
    {
        var control = (BulletPointItem)bindable;
        var newSpansValue = (ObservableCollection<Span>)newValue;
        var formattedString = new FormattedString();

        if (control == null)
            return;

        if (newSpansValue == null || newSpansValue.Count == 0)
        {
            control.LabelContent.FormattedText = formattedString;
            return;
        }

        foreach (var span in newSpansValue)
        {
            formattedString.Spans.Add(span);
        }

        control.LabelContent.FormattedText = formattedString;
    }
}

Попытка использования:

                            <controls:BulletPointItem>
                                <Span Text="Span 1." />
                                <Span FontAttributes="Italic" Text="Span 2." />
                            </controls:BulletPointItem>

1 Ответ

0 голосов
/ 01 октября 2019

Причина: Пределы - это ObservableCollection . Поэтому, если вы хотите установить его значение, вы должны определить коллекцию в xaml, а не перечислять Span напрямую.

Решение:

Я все же предлагаю вам использовать привязку данных, так какВы установили его как BindableProperty .

<controls:BulletPointItem BackgroundColor="LightBlue" Spans="{Binding Spans}">

И в коде позади или ViewModel

public static readonly BindableProperty SpansProperty =
        BindableProperty.Create(
        nameof(Spans),
        typeof(ObservableCollection<Span>),
        typeof(BulletPointItem),
        defaultValueCreator: bindable => new ObservableCollection<Span>(),
        propertyChanged: OnSpansChanged);
public ObservableCollection<Span> spans { get; set; }
spans = new ObservableCollection<Span>() {

      new Span(){Text="Span1" },
      new Span(){Text="Span2",FontAttributes=FontAttributes.Italic }
};

Это будет более гибким, когдаВы хотите добавить или удалить элементы из него.

Обновление

Когда вы устанавливаете промежутки исключительно из XAML. Это добавит элементы в Пролеты . Но метод OnSpansChanged будет вызываться только при установке нового значения. Таким образом, вы можете обработать логику в методе CollectionChanged . Он будет вызываться каждый раз, когда вы добавляете новый элемент в Spans.

public BulletPointItem()
{
  InitializeComponent();

  Spans.CollectionChanged += Spans_CollectionChanged;
}

// this method will been invoked 2 times if you add two span in xaml
private void Spans_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
   var collection = sender as ObservableCollection<Span>;
  //...  
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...