Как использовать другой базовый класс в настраиваемом элементе управления в зависимости от целевой платформы?

У меня есть собственный редактор, который я использую для iOS, но для UWP я использую другой редактор под названием SfRichTextEditor.

Теперь мне интересно, как я могу создать как разделяемый класс, поскольку у них есть те же самые связываемые свойства вместо того, чтобы делать то, что я делаю сейчас, то есть создает ContentView поверх них, что вызывает:

  1. ненужное вложение для повышения производительности

  2. повторяющийся код

  3. похоже есть проблемы с некоторыми привязками (не проверено, но что-то странное).

    <ContentView>
        <OnPlatform x:TypeArguments="View">
            <OnPlatform.Platforms>
                <On Platform="iOS">
    
                    <controls:CustomIOSEditor/>
                </On>
                <On Platform="UWP">
                    <controls:CustomUWPEditor/>
                </On>
            </OnPlatform.Platforms>
        </OnPlatform>
    </ContentView>
    

Поэтому вместо этого подхода я хочу иметь общий базовый класс, если это возможно, чтобы повторно использовать код.

Это элементы управления x2, которые у меня есть сегодня.

Мой пользовательский элемент управления iOS:

public class CustomIOSEditor : Editor // Using regular xamarin editor
{
    public static readonly BindableProperty StringResultCommandProperty =
        BindableProperty.Create(
            nameof(StringResultCommand),
            typeof(ICommand),
            typeof(CustomIOSEditor),
            default(ICommand));

    public object StringResultCommandParameter
    {
        get => GetValue(StringResultCommandParameterProperty);
        set => SetValue(StringResultCommandParameterProperty, value);
    }
}

Мой пользовательский элемент управления UWP:

public class CustomUWPEditor : SfRichTextEditor // Using SfRichTextEditor instead here.
{
    public static readonly BindableProperty StringResultCommandProperty =
        BindableProperty.Create(
            nameof(StringResultCommand),
            typeof(ICommand),
            typeof(CustomUWPEditor),
            default(ICommand));

    public object StringResultCommandParameter
    {
        get => GetValue(StringResultCommandParameterProperty);
        set => SetValue(StringResultCommandParameterProperty, value);
    }
}

Последняя подсказка **  введите описание изображения здесь ОБНОВЛЕНИЕ ** Общий .csproj:  введите описание изображения здесь

MacOS:  введите описание изображения здесь

Настройки:  введите описание изображения здесь

Ошибка:  введите описание изображения здесь


person DiddanDo    schedule 09.01.2021    source источник
comment
Проверь сейчас. Итак, это тот, который я выделяю, первые два вы можете игнорировать   -  person DiddanDo    schedule 10.01.2021
comment
Да, я сделал. Также перезапущена визуальная студия. По-прежнему та же проблема.   -  person DiddanDo    schedule 10.01.2021
comment
Кстати, я использую формы xamarn.   -  person DiddanDo    schedule 10.01.2021
comment
Да, я конечно знаю, что это XF (иначе это не имеет смысла), .__ MACOS__. похоже, работает, как ожидалось, и все в коде кажется хорошим, извините, я пока не знаю.   -  person Cfun    schedule 10.01.2021
comment
В порядке. Мне не нужно менять что-либо, относящееся к MacOS?   -  person DiddanDo    schedule 10.01.2021
comment
Нет, когда я реализовал свое приложение (только для Android), мне не пришлось ничего менять в собственном (Android) .csproj файле.   -  person Cfun    schedule 10.01.2021
comment
это происходит, когда вы создаете / развертываете только MacOS или даже с uwp?   -  person Cfun    schedule 10.01.2021
comment
ладно ладно. Я думаю, что проект macOS - это netstandard 2.0, и поэтому он может не работать? но не уверен, что 2.1 работает   -  person DiddanDo    schedule 10.01.2021
comment
еще не пробовал UWP. Я могу попробовать iOS через 30 минут, чтобы увидеть.   -  person DiddanDo    schedule 10.01.2021
comment
К сожалению, проблемы по-прежнему возникают: /   -  person DiddanDo    schedule 12.01.2021
comment
Но, возможно, нашел ключ к разгадке. См. Изображение, которое я загрузил.   -  person DiddanDo    schedule 12.01.2021
comment
Вы исправили ошибку сборки? Не говорите мне, что проблема заключалась в том, что у вас был общий проект xf как запускаемый?   -  person Cfun    schedule 12.01.2021
comment
Не исправил нет. Я использую обычный проект форм xam.   -  person DiddanDo    schedule 12.01.2021


Ответы (2)


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

Проект Xamarin.Forms не поддерживает фреймворки с множественным таргетингом, наоборот, напротив него эволюция, которая называется MAUI will.

Между тем вы можете использовать MSBuild SDK Extras SDK вместо используемого по умолчанию Microsoft.NET.Sdk an ( но имейте в виду, что он официально не поддерживается), но конечный результат отличный (проверка во время компиляции).

  • В YourSharedProject.csproj измените <Project Sdk="Microsoft.NET.Sdk"> на <Project Sdk="MSBuild.Sdk.Extras/2.1.2">.
  • Настройте платформы, на которые нацелены ваши проекты, и их версию:

Пример, если вы нацеливаетесь на netstandard2.1 и iOS 10, а затем измените <TargetFramework>netstandard2.1</TargetFramework> на <TargetFrameworks>netstandard2.1;iOS10</TargetFrameworks>, начав сначала с netstandardxx.

  • Taget Uwp: <TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">$(TargetFrameworks);uap10.0.17763;netcoreapp3.1;net472</TargetFrameworks> (если у вас установлен .net framework 4.7.1 вместо 4.7.2, замените net472 на net471 (то же самое для версий .net.core и uwp).

В конце концов, ваш запуск файла .csproj будет выглядеть так:

<Project Sdk="MSBuild.Sdk.Extras/2.1.2">
    <PropertyGroup>
        <TargetFrameworks>netstandard2.1;iOS10</TargetFrameworks>
        <TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">
$(TargetFrameworks);uap10.0.17763;netcoreapp3.1;net472</TargetFrameworks>

Все это позволит вам использовать символические константы при условной проверке времени компиляции:

public class CustomIOSEditor : 
#if __iOS__
           Editor     //will inherit from this if we are building against iOS
#endif
#if WINDOWS_UWP      //will inherit from this if we are building against uwp
           SfRichTextEditor
#endif
{
    public static readonly BindableProperty StringResultCommandProperty =
        BindableProperty.Create(
            nameof(StringResultCommand),
            typeof(ICommand),
            typeof(CustomIOSEditor),
            default(ICommand));

    public object StringResultCommandParameter
    {
        get => GetValue(StringResultCommandParameterProperty);
        set => SetValue(StringResultCommandParameterProperty, value);
    }
}

Для таргетинга на другие платформы-версии:

  • Mac версии 20: Xamarin.Mac20
  • Версия Android 10.0: MonoAndroid10.0
  • tizen, версия 40: tizen40
person Cfun    schedule 09.01.2021
comment
Ого, это действительно очень мило. Я попробую сейчас посмотреть, работает ли он. Есть идеи, есть ли какие-нибудь известные ошибки (поскольку они еще официально не поддерживаются)? - person DiddanDo; 10.01.2021
comment
Вы знаете, что печатать, например, в macOS? ‹TargetFrameworkVersion› v2.0 ‹/TargetFrameworkVersion› ‹TargetFrameworkIdentifier› Xamarin.Mac ‹/TargetFrameworkIdentifier› это целевая версия, которую я нахожу, копаясь в ее .csproj - person DiddanDo; 10.01.2021
comment
Действительно Xamarin.Mac + версия добавлена ​​без пробела. Я обновил свой ответ. В случае ошибок вы всегда можете воспользоваться репо, которое я связал, и просмотреть / issues. - person Cfun; 10.01.2021
comment
Хм, есть проблемы. Компилятору требуется около 20 секунд, чтобы вычислить, что ему не хватает Type для настраиваемого класса. Не уверен, что это потому, что xamarin mac не 2.1. поддерживается? Я не уверен, как сделать его совместимым с 2.1. - person DiddanDo; 10.01.2021
comment
Я тестирую оба - ‹TargetFrameworks› netstandard2.1; Xamarin.Mac20 ‹/TargetFrameworks›, а также ‹TargetFrameworks› netstandard2.0; Xamarin.Mac20 ‹/TargetFrameworks› - person DiddanDo; 10.01.2021
comment
Хм, я полагаю, у меня тоже есть последняя версия? Где я могу это проверить? Я новичок в разработке для Xamarin.Mac - person DiddanDo; 10.01.2021
comment
Не могли бы вы поделиться ошибкой, может быть, проблема в вашем проекте? (честно говоря, у меня нет опыта разработки Mac ..) - person Cfun; 10.01.2021
comment
Проверьте обновленную публикацию, чтобы увидеть скриншоты проблемы + настройки. И чтобы объяснить ошибку, я могу нажать кнопку воспроизведения, она строится в течение 20 секунд, а затем дает мне ожидаемый тип (CS1031), в котором находится унаследованный класс (не отображается красным, хотя, как и следовало ожидать от IDE) - person DiddanDo; 10.01.2021

Вы ищете SetNativeControl().

Например, посмотрите этот пример,

https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/custom-renderer/view#creating-the-custom-renderer-on-uwp

Вставка того же образца из приведенной выше ссылки здесь

ПРИМЕЧАНИЕ. CameraPreview в приведенном ниже примере - это элемент Xamarin.Form, а CaptureElement - это элемент управления UWP.

[assembly: ExportRenderer(typeof(CameraPreview), typeof(CameraPreviewRenderer))]
namespace CustomRenderer.UWP
{
    public class CameraPreviewRenderer : ViewRenderer<CameraPreview, Windows.UI.Xaml.Controls.CaptureElement>
    {
        ...
        CaptureElement _captureElement;
        bool _isPreviewing;

        protected override void OnElementChanged(ElementChangedEventArgs<CameraPreview> e)
        {
            base.OnElementChanged(e);

            if (e.OldElement != null)
            {
                // Unsubscribe
                Tapped -= OnCameraPreviewTapped;
                ...
            }
            if (e.NewElement != null)
            {
                if (Control == null)
                {
                  ...
                  _captureElement = new CaptureElement();
                  SetupCamera();
                  SetNativeControl(_captureElement);
                }
            }
        }

        ...
    }
}
person Yogesh    schedule 09.01.2021
comment
разве использование настраиваемого рендерера в этом случае не излишество? Я не понимаю, как это исправить от дублирования кода? - person Cfun; 09.01.2021
comment
Да, тогда мне нужно было бы написать программный код для платформ, я думаю, должны быть лучшие способы решить эту проблему. - person DiddanDo; 10.01.2021