Вопрос или проблема
Я пытаюсь понять, что я делаю не так при создании пользовательского элемента управления .NET MAUI с использованием ContentView. Я много раз читал документацию, но так и не смог добиться ожидаемого поведения. Возможно, я ожидаю неправильный результат. Я пишу этот элемент управления полностью на C# без XAML и использую пакет CommunityToolkit.Maui.Markup для привязки к компоненту. Пользовательский элемент управления определен следующим образом:
public partial class Elevation : ContentView
{
public static readonly BindableProperty TapCommandProperty = BindableProperty.Create(
nameof(TapCommand),
typeof(ICommand),
typeof(Elevation),
default(ICommand));
public ICommand TapCommand
{
get => (ICommand)GetValue(TapCommandProperty);
set => SetValue(TapCommandProperty, value);
}
public static readonly BindableProperty CornerRadiusProperty = BindableProperty.Create(
nameof(CornerRadius),
typeof(CornerRadius),
typeof(Elevation),
new CornerRadius(5));
public CornerRadius CornerRadius
{
get => (CornerRadius)GetValue(CornerRadiusProperty);
set => SetValue(CornerRadiusProperty, value);
}
new public static readonly BindableProperty ShadowProperty = BindableProperty.Create(
nameof(Shadow),
typeof(Shadow),
typeof(Elevation),
new Shadow());
new public Shadow Shadow
{
get => (Shadow)GetValue(ShadowProperty);
set => SetValue(ShadowProperty, value);
}
public Elevation()
{
Content = new Border()
{
Content = Content
}.Bind(PaddingProperty, nameof(Padding), source: this)
.Bind(BackgroundColorProperty, nameof(BackgroundColor), source: this)
.Bind(ShadowProperty, nameof(Shadow), source: this)
.Bind(Border.StrokeShapeProperty, nameof(CornerRadius), source: this, converter: new CornerRadiusToRoundRectangleConverter());
}
}
public class CornerRadiusToRoundRectangleConverter : IValueConverter
{
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (value is CornerRadius cornerRadius)
{
return new RoundRectangle { CornerRadius = cornerRadius };
}
return new RoundRectangle { CornerRadius = new CornerRadius(5) };
}
public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
И вот как я ожидаю использовать его, исходя из того, что я до сих пор прочитал/узнал:
new Elevation()
{
Padding = 10,
TapCommand = action,
CornerRadius = new CornerRadius(5, 30, 5, 30),
Content = new Grid()
{
Children =
{
new Grid()
{
ColumnDefinitions = Columns.Define(25, Star, Star),
Children =
{
icon.IconSize(15).CenterVertical().IconColor(ColorExtensions.FromStaticResource("Primary")).Column(0),
new Label()
.Text(actionName)
.Font(size: 18)
.Column(1),
new MauiIcon()
.End()
.CenterVertical()
.Icon(FontAwesomeSolidIcons.ChevronRight)
.IconSize(12.5)
.Column(2)
}
}
}
}
}.AppThemeColorBinding(
BackgroundColorProperty,
ColorExtensions.FromStaticResource("Gray200"),
ColorExtensions.FromStaticResource("Gray900"));
Свойства Padding и BackgroundColor применяются правильно и видны в пользовательском интерфейсе, но свойства Shadow и StrokeShape не отображаются в пользовательском интерфейсе. Я также не уверен, что правильно использую свойство Content. Есть ли какие-либо мысли, так как у меня больше не осталось идей?
Ответ или решение
Конечно, давайте разберем вашу реализацию пользовательского контрола в .NET MAUI и выявим возможные проблемы.
Проблемы и исправления
-
Использование свойства
Content
:
В вашем конструкторе, когда вы задаетеContent
дляContentView
, вы меняете его на новый экземплярBorder
, но затем вы пытаетесь назначитьContent
внутри этого новогоBorder
, что указывает снова наContentView
. В результате происходит цикл, так как свойствоContent
ссылается на себя. Вместо этого, вы должны назначить ваш пользовательский контент как содержимоеBorder
.Измените конструкцию
Content
на следующую:public Elevation() { var border = new Border() { // Устанавливаем здесь для новых контентов, а не на ContentView Content = new ContentView() // предполагается, что это будет ваш контент }; Content = border; // Применяем биндинги border.Bind(PaddingProperty, nameof(Padding), source: this) .Bind(BackgroundColorProperty, nameof(BackgroundColor), source: this) .Bind(ShadowProperty, nameof(Shadow), source: this) .Bind(Border.StrokeShapeProperty, nameof(CornerRadius), source: this, converter: new CornerRadiusToRoundRectangleConverter()); }
-
Применение свойства
Shadow
:
Uбедитесь, что ваш типShadow
правильно реализован и используется вBorder
. В .NET MAUI свойствоShadow
должно поддерживаться корректно, если используется в UI. Проверьте, что ваша версия .NET MAUI актуальна и поддерживает нужные свойства. -
Отображение
CornerRadius
:
Ваш конвертерCornerRadiusToRoundRectangleConverter
выглядит в целом правильно, но убедитесь, чтоCornerRadius
применяется к нужному свойству. В методеConvert
проверьте, действительно ли используетсяRoundRectangle
, и что оно правильно работает сBorder
. Попробуйте временно добавить обработку вывода вDebug
, чтобы проверить, возвращается ли нужное значение. -
Используйте интерфейс
ICommand
:
Убедитесь, чтоTapCommand
реализует интерфейсICommand
и что команда привязывается корректно. Проверьте наличие реализации команды, например,RelayCommand
изCommunityToolkit.Mvvm
или аналогичной реализации, которая вызывает нужный метод.
Пример использования
Ваш пример использования Elevation
может выглядеть следующим образом, однако убедитесь, что изменения, предложенные выше, выполнены:
var action = new Command(() => { /* ваша логика */ });
var elevation = new Elevation()
{
Padding = 10,
TapCommand = action,
CornerRadius = new CornerRadius(5, 30, 5, 30),
Content = new Grid()
{
Children =
{
new Grid()
{
ColumnDefinitions = Columns.Define(25, Star, Star),
Children =
{
icon.IconSize(15).CenterVertical().IconColor(ColorExtensions.FromStaticResource("Primary")).Column(0),
new Label()
.Text(actionName)
.Font(size: 18)
.Column(1),
new MauiIcon()
.End()
.CenterVertical()
.Icon(FontAwesomeSolidIcons.ChevronRight)
.IconSize(12.5)
.Column(2)
}
}
}
}
}.AppThemeColorBinding(
BackgroundColorProperty,
ColorExtensions.FromStaticResource("Gray200"),
ColorExtensions.FromStaticResource("Gray900"));
Заключение
Проверьте каждое из предложенных изменений, чтобы убедиться, что свойства Shadow
и CornerRadius
корректно применяются. Сравните вашу реализацию с примерами, представленными в документации .NET MAUI, чтобы убедиться в правильности подхода.
Если после всех этих изменений проблема все еще существует, возможно, вам стоит рассмотреть возможность тестирования с помощью простых значений для свойств Shadow
и CornerRadius
, чтобы изолировать проблему.