C# 如何根据平台目标在自定义控件中使用不同的基类?

C# 如何根据平台目标在自定义控件中使用不同的基类?,c#,xamarin,xamarin.forms,custom-controls,multitargeting,C#,Xamarin,Xamarin.forms,Custom Controls,Multitargeting,我有一个用于iOS的自定义编辑器,但对于UWP,我使用另一个名为SfRichTextEditor的编辑器 现在我想知道如何创建一个像可共享类一样的类,因为它们具有相同的bindableproperties,而不是像我现在做的那样,在它们上面创建一个ContentView,这导致: 出于性能目的不必要的嵌套 重复代码 似乎有些绑定有问题(未验证,但有些奇怪) 我的UWP自定义控件: public class CustomIOSEditor : Editor // Using regular x

我有一个用于iOS的自定义编辑器,但对于UWP,我使用另一个名为
SfRichTextEditor
的编辑器

现在我想知道如何创建一个像可共享类一样的类,因为它们具有相同的bindableproperties,而不是像我现在做的那样,在它们上面创建一个
ContentView
,这导致:

  • 出于性能目的不必要的嵌套

  • 重复代码

  • 似乎有些绑定有问题(未验证,但有些奇怪)

    我的UWP自定义控件:

    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);
        }
    }
    
    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:

    马科斯:

    设置:

    错误:

    您正在寻找的是
    SetNativeControl()

    举个例子

    从上面的链接粘贴相同的样本到这里

    注意-
    CameraPreview
    在下面的示例中是Xamarin。表单元素和
    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);
                    }
                }
            }
    
            ...
        }
    }
    
    [程序集:导出渲染器(typeof(CameraPreview)、typeof(CameraPreviewRenderer))]
    命名空间CustomRenderer.UWP
    {
    公共类CameraPreviewRenderer:ViewRenderer
    {
    ...
    CaptureElement\u CaptureElement;
    布尔!;
    受保护的覆盖无效OnElementChanged(ElementChangedEventArgs e)
    {
    基础。一个要素发生变化(e);
    if(e.OldElement!=null)
    {
    //退订
    分接-=一次检查后的分接;
    ...
    }
    if(例如NewElement!=null)
    {
    if(Control==null)
    {
    ...
    _captureElement=新captureElement();
    设置摄像头();
    SetNativeControl(_captureElement);
    }
    }
    }
    ...
    }
    }
    
    由于除了继承不同之外,所有代码都是通用的,因此最好使用编译时检查(在这种情况下,不必担心代码会变得凌乱)

    Xamarin.Forms项目不支持多目标框架

    同时,您可以使用SDK代替默认的
    Microsoft.NET.SDK
    an(但请记住,它不是官方支持的),但最终结果是整洁的(编译时检查)

    • YourSharedProject.csproj
      中,将
      更改为
    • 设置项目所针对的平台及其版本:
    例如,如果您以netstandard2.1和iOS 10为目标,则将
    netstandard2.1
    更改为
    netstandard2.1;iOS10
    首先从
    netstandardxx
    开始

    • Taget-Uwp:
      $(TargetFrameworks);uap10.0.17763;netcoreapp3.1;net472
      (如果安装的是.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>
    

    针对其他平台版本:

    • Mac版本20:
      Xamarin.Mac20
    • 安卓10.0版:
      MonoAndroid10.0
    • tizen版本40:
      tizen40

    在这种情况下使用自定义渲染器不是一种过分的做法吗?我不知道这将如何弥补“重复代码”的问题?是的,那么我必须为平台编写特定于平台的代码,我认为应该有更好的方法来解决它。哦,哇,这确实很好。我现在就去看看它是否有效。知道是否有任何已知的bug(因为它还没有得到官方支持)?你知道在macOS上键入什么吗?例如,v2.0 Xamarin.Mac这是我在挖掘其.csprojinded
    Xamarin.Mac
    +附加版本时发现的目标版本,没有任何空格。我已更新了我的答案。对于bug,你可以随时查看我链接的repo,并查看/issues.Hmm有问题。它需要compiler需要20秒来计算它是否缺少自定义类的类型。不确定这是否是因为xamarin mac不支持2.1?我不确定如何使其2.1兼容。我测试了-netstandard2.1;xamarin.Mac20和netstandard2.0;xamarin.Mac20。现在检查一下。这是我突出显示的一个,前两个u可以忽略是的我做了。也重新启动了visual studio。仍然是相同的问题。我使用xamarn forms btw。是的,我当然知道它是XF(否则就没有意义了),。\uuuuMacOS\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu?
    <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);
        }
    }