Стиль Xamarin не применяется к пользовательскому представлению

Создаю индивидуальные Frame и View. Я объединил Frame и View в Page с Style ресурсами, как показано ниже.

Главная страница

<ContentPage.Resources>
    <Style x:Key = "Style" TargetType = "local:MyFrame">
        <Setter Property = "HorizontalOptions" Value = "FillAndExpand" />
        <Setter Property = "BackgroundColor" Value = "LimeGreen" />
    </Style>
</ContentPage.Resources>
<local:MyView>
    <local:MyView.Views>
        <local:MyFrame Style = "{StaticResource Style}"
                        HorizontalOptions = "FillAndExpand"
                        Title = "Number one" />
    </local:MyView.Views>
</local:MyView>

Мой взгляд

public class MyView : ContentView
{
    private readonly StackLayout _layout;
    public ObservableCollection<View> Views { get; set; }

    public MyView()
    {
        Views = new ObservableCollection<View>();
        Views.CollectionChanged += OnViewsCollectionChanged;

        _layout = new StackLayout();
        Content = _layout;
    }

    private void OnViewsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.OldItems != null)
            foreach (View view in e.OldItems)
                _layout.Children.Remove(view);

        if (e.NewItems != null)
            foreach (View view in e.NewItems)
                _layout.Children.Add(view);
    }
}

Мой фрейм

public class MyFrame : Frame
{
    private readonly Label _title;
    public string Title { set => _title.Text = value; }

    public MyFrame()
    {
        BackgroundColor = Color.LightPink;

        _title = new Label
        {
            TextColor = Color.Black,
            FontSize = 16,
        };

         Content = _title;
    }
}

Я ожидал цвет LimeGreen на фоне MyFrame, потому что я установил MyFrame.Style в MainPage, однако фактический результат — светло-розовый.

Я предполагаю, что установка BackgroundColor в конструкторе MyFrame не означает установку по умолчанию. Тогда как я могу установить BackgroundColor по умолчанию для MyFrame?

Я упростил реальный проект до небольшого воспроизводимого проекта. Вот Github


Обновлять

Закомментируйте код BackgroundColor = Color.LightPink;, в результате получится цвет LimeGreen... Тогда как мне установить MyFrame.BackgroundColor по умолчанию?

Что вы имеете в виду по умолчанию? Style применяет BackgroundColor по умолчанию, а затем вы переопределяете его, явно настроив его под своим контролем.

Bijington 22.12.2020 09:56
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
1
214
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я мог бы воспроизвести вашу проблему, и я могу предложить следующую модификацию вашего кода, чтобы иметь возможность установить BackgroundColor по умолчанию для вашего представления MyFrame:

Модификации MyFrame

Чтобы решить вашу проблему, я изменил MyFrame, чтобы он был определен в Xaml:

MyFrameXaml.xaml

<?xml version = "1.0" encoding = "UTF-8"?>
<Frame xmlns = "http://xamarin.com/schemas/2014/forms" 
       xmlns:x = "http://schemas.microsoft.com/winfx/2009/xaml"
       x:Class = "StyleDoesNotApply.MyFrameXAML"
       BackgroundColor = "{Binding MyBackgroundColor}">
    <Label x:Name = "title"
           TextColor = "Black"
           FontSize = "16"/>
</Frame>

Затем в коде задайте свойство MyBackgroundColor следующим образом:

MyFrameXaml.xaml.cs

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace StyleDoesNotApply
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class MyFrameXAML : Frame
    {

        public string Title { set => title.Text = value; }


        public static readonly BindableProperty MyBackgroundColorProperty =
            BindableProperty.Create(nameof(MyBackgroundColor), typeof(Color), typeof(MyFrame), Color.LightPink);

        public Color MyBackgroundColor
        {
            get => (Color)GetValue(MyBackgroundColorProperty);
            set => SetValue(MyBackgroundColorProperty, value);
        }


        public MyFrameXAML()
        {

            BindingContext = this;
            InitializeComponent();
            
        }
    }
}

Используйте новый вид

<ContentPage.Resources>
    <Style x:Key = "Style" TargetType = "local:MyFrameXAML">
        <Setter Property = "HorizontalOptions" Value = "StartAndExpand" />
        <Setter Property = "MyBackgroundColor" Value = "LimeGreen" />
    </Style>
</ContentPage.Resources>

<StackLayout>
    <Label Text = "Style does apply!"
           FontSize = "Title"
           TextColor = "Black"/>
    <local:MyView>
        <local:MyView.Views>
            <local:MyFrameXAML Style = "{StaticResource Style}"
                               HorizontalOptions = "FillAndExpand"
                               Title = "Number one" />
        </local:MyView.Views>
    </local:MyView>

</StackLayout>

Обновлять

Многоразовый код

public static BindableProperty Override(
    this BindableProperty bindableProperty,
    string propertyName = null,
    Type returnType = null,
    Type declaringType = null,
    object defaultValue = null,
    BindingMode defaultBindingMode = BindingMode.OneWay,
    BindableProperty.ValidateValueDelegate validateValue = null,
    BindableProperty.BindingPropertyChangedDelegate propertyChanged = null,
    BindableProperty.BindingPropertyChangingDelegate propertyChanging = null,
    BindableProperty.CoerceValueDelegate coerceValue = null,
    BindableProperty.CreateDefaultValueDelegate defaultValueCreator = null)
{
    if (string.IsNullOrEmpty(propertyName))
        propertyName = bindableProperty.PropertyName;
    if (returnType == null)
        returnType = bindableProperty.ReturnType;
    if (declaringType == null)
        declaringType = bindableProperty.DeclaringType;
    if (defaultValue == null)
        defaultValue = bindableProperty.DefaultValue;

    if (propertyChanged == null)
        propertyChanged = (bindable, oldValue, newValue) =>
        {
            var property = bindableProperty.DeclaringType.GetProperty(bindableProperty.PropertyName);
            property.SetValue(bindable, newValue);
        };

    return BindableProperty.Create(propertyName, returnType, declaringType, defaultValue, defaultBindingMode,
        validateValue, propertyChanged, propertyChanging, coerceValue, defaultValueCreator);
}
public class MyFrame : Frame
{
    // override existing BindableProperty
    public static new readonly BindableProperty BackgroundColorProperty = VisualElement.BackgroundColorProperty.Override();

    private readonly Label _title;
    public string Title { set => _title.Text = value; }

    public MyFrame()
    {
        BackgroundColor = Color.LightPink;

        _title = new Label
        {
            TextColor = Color.Black,
            FontSize = 16,
        };

         Content = _title;
    }
}

Другие вопросы по теме