C# 如何基于Xamarin(XAML)中的平台将编辑器的不同属性绑定到同一变量

C# 如何基于Xamarin(XAML)中的平台将编辑器的不同属性绑定到同一变量,c#,xaml,xamarin,xamarin.forms,data-binding,C#,Xaml,Xamarin,Xamarin.forms,Data Binding,我正在尝试将CustomEditor的属性PlainText(这是我在我的CustomEditor中创建的双向可绑定属性)绑定到启用iOS时的变量KeyString,并在启用Android时将属性Text绑定到KeyString 我知道,在iOS上,将明文绑定到按键串可以正常工作(我已经进行了测试以确保这一点),但是安卓将文本绑定到按键串会在系统中失败。ArgumentNullException值不能为空。参数名称:绑定 另外,IntelliSense在x:TypeAgruments中使用Bin

我正在尝试将
CustomEditor
的属性
PlainText
这是我在我的CustomEditor中创建的双向可绑定属性)绑定到启用
iOS
时的变量
KeyString
,并在启用
Android
时将属性
Text
绑定到
KeyString

我知道,在
iOS
上,将
明文
绑定到
按键串
可以正常工作(我已经进行了测试以确保这一点),但是
安卓
文本
绑定到
按键串
会在
系统中失败。ArgumentNullException
值不能为空。参数名称:绑定

另外,IntelliSense
x:TypeAgruments
中使用
BindingBase
的代码部分加下划线。对于第一部分,Intellisense说:
明文不支持OnPlatform(BindingBase)
类型的值,但是当我在我的
iOS
模拟器上运行它时,代码仍然有效。它给我的错误是,
文本不支持代码的
Android
绑定部分的OnPlatform(BindingBase)
类型的值,而这是它无法运行的XAML部分

下面是我的
XAML
代码,你知道我可能做错了什么吗

<Frame Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" BorderColor="Black" Margin="0" Padding="0">
     <controls:CustomEditor HeightRequest="80" IsPassword="True">
         <controls:CustomEditor.PlainText>
             <OnPlatform x:TypeArguments="BindingBase">
                 <On Platform="iOS" Value="{Binding KeyString}"/>
             </OnPlatform>
         </controls:CustomEditor.PlainText>

         <controls:CustomEditor.Text>
             <OnPlatform x:TypeArguments="BindingBase">
                 <On Platform="Android" Value="{Binding KeyString}"/>
             </OnPlatform>
         </controls:CustomEditor.Text>

         <controls:CustomEditor.Effects>
             <controls:PasswordEffect>
             </controls:PasswordEffect>
         </controls:CustomEditor.Effects>
     </controls:CustomEditor>
</Frame>

OnPlatform的x:TypeArguments表示要绑定的值的类型,在本例中,
KeyString
的类型为
string
。看一看


OnPlatform的x:TypeArguments表示要绑定的值的类型,在您的示例中,
键串
的类型为
字符串
。看一看


由于我不喜欢在平台上使用
,我想提出一个我在评论中提到的解决方法

在您的
CustomEditor
中添加以下代码:

公共静态BindableProperty CustomTitleProperty=BindableProperty.Create( propertyName:nameof(CustomTitle), returnType:typeof(字符串), declaringType:typeof(CustomEditor), 默认值:空); 公共字符串自定义标题 { get{return(string)GetValue(CustomTitleProperty);} set{SetValue(CustomTitleProperty,value);} } 受保护的重写无效OnPropertyChanged([CallerMemberName]字符串propertyName=null) { base.OnPropertyChanged(propertyName); 如果(propertyName==CustomTitleProperty.propertyName) { SetCustomTitle(); } } 私有void SetCustomTitle() { 交换机(设备运行时平台) { case Device.iOS: { 纯文本=自定义标题; 返回; } case设备。Android: { 文本=自定义标题; 返回; } 违约: { 抛出新的NotSupportedException($“{nameof(SetCustomTitle)}中不支持{Device.RuntimePlatform}”); } } } 我所做的只是将平台上的代码移到您的控件中,这样您就可以保持xaml代码更干净

使用这种方法,您应该能够像这样使用它


由于我不喜欢在平台上使用
,我想提出一个我在评论中提到的解决方法

在您的
CustomEditor
中添加以下代码:

公共静态BindableProperty CustomTitleProperty=BindableProperty.Create( propertyName:nameof(CustomTitle), returnType:typeof(字符串), declaringType:typeof(CustomEditor), 默认值:空); 公共字符串自定义标题 { get{return(string)GetValue(CustomTitleProperty);} set{SetValue(CustomTitleProperty,value);} } 受保护的重写无效OnPropertyChanged([CallerMemberName]字符串propertyName=null) { base.OnPropertyChanged(propertyName); 如果(propertyName==CustomTitleProperty.propertyName) { SetCustomTitle(); } } 私有void SetCustomTitle() { 交换机(设备运行时平台) { case Device.iOS: { 纯文本=自定义标题; 返回; } case设备。Android: { 文本=自定义标题; 返回; } 违约: { 抛出新的NotSupportedException($“{nameof(SetCustomTitle)}中不支持{Device.RuntimePlatform}”); } } } 我所做的只是将平台上的代码移到您的控件中,这样您就可以保持xaml代码更干净

使用这种方法,您应该能够像这样使用它



您为什么不能在CustomEditor中根据平台设置文本?在这种情况下,您可以将值绑定到控件中的属性和处理平台什么是CustomEditor?有取景模型吗?[m.v.c.e]please@lawiluk谢谢你的评论,这听起来很合理,你能进一步解释一下吗?关于如何做到这一点,我只是用一个简单的绑定测试你的代码,它在Android端工作,你能分享更多的代码来重现这个问题吗?@JackHua MSFT我分享了更多的代码,希望这会有所帮助,如果您想查看更具体的内容,请告诉我您为什么不能在CustomEditor中根据平台设置文本?在这种情况下,您可以将值绑定到属性和handl
using System;
using System.Collections.Generic;
using System.Text;
using Xamarin.Forms;

namespace MyApp.CustomControls
{
    public class CustomEditor : Editor
    {
        public static readonly BindableProperty IsPasswordProperty =
         BindableProperty.Create(nameof(IsPassword), typeof(bool), typeof(CustomEditor), false);

        public static readonly BindableProperty PlainTextProperty =
            BindableProperty.Create(nameof(PlainText),
                typeof(string),
                typeof(CustomEditor),
                String.Empty,
                defaultBindingMode:BindingMode.TwoWay,
                propertyChanged:OnPlainTextChanged);

        public bool IsPassword
        {
            get { return (bool)GetValue(IsPasswordProperty); }
            set { SetValue(IsPasswordProperty, value); }
        }

        public string PlainText {
            get { return (string)GetValue(PlainTextProperty); }
            set { SetValue(PlainTextProperty, value); }
        }

        private static void OnPlainTextChanged(BindableObject bindable, object oldValue, object newValue)
        {
            var control = (CustomEditor)bindable;
            if (newValue != null)
            {
                control.PlainText = newValue.ToString();
            }
        }
    }
}
<Frame Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" BorderColor="Black" Margin="0" Padding="0">
     <controls:CustomEditor HeightRequest="80" IsPassword="True">
         <controls:CustomEditor.PlainText>
             <OnPlatform x:TypeArguments="{x:Type x:String}">
                 <On Platform="iOS" Value="{Binding KeyString}"/>
             </OnPlatform>
         </controls:CustomEditor.PlainText>

         <controls:CustomEditor.Text>
             <OnPlatform x:TypeArguments="{x:Type x:String}">
                 <On Platform="Android" Value="{Binding KeyString}"/>
             </OnPlatform>
         </controls:CustomEditor.Text>

         <controls:CustomEditor.Effects>
             <controls:PasswordEffect>
             </controls:PasswordEffect>
         </controls:CustomEditor.Effects>
     </controls:CustomEditor>
</Frame>