我正在尝试将CustomEditor
的属性PlainText
(这是我在自定义编辑器中创建的双向可绑定属性(绑定到变量KeyString
时iOS
,并在Android
时将属性Text
绑定到KeyString
。
我知道PlainText
与KeyString
的绑定在iOS
工作正常(我已经测试以确保这一点(,但是Text
与KeyString
的绑定Android
失败,System.ArgumentNullException
Value cannot be null. Parameter name: binding
智能感知还强调了我的代码中在x:TypeAgruments
中使用BindingBase
的部分。对于第一部分,智能感知说:PlainText does not support values of type OnPlatform(BindingBase)
,但是当我在iOS
模拟器上运行它时,代码仍然有效。它为我提供了代码Android
绑定部分的错误Text does not support values of type 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>
在我的自定义编辑器类中,我有以下代码:
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();
}
}
}
}
由于我不喜欢与OnPlatform
一起工作,我想提出我在评论中提到的解决方法。
在CustomEditor
中添加以下代码:
public static BindableProperty CustomTitleProperty = BindableProperty.Create(
propertyName: nameof(CustomTitle),
returnType: typeof(string),
declaringType: typeof(CustomEditor),
defaultValue: null);
public string CustomTitle
{
get { return (string)GetValue(CustomTitleProperty); }
set { SetValue(CustomTitleProperty, value); }
}
protected override void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
base.OnPropertyChanged(propertyName);
if(propertyName==CustomTitleProperty.PropertyName)
{
SetCustomTitle();
}
}
private void SetCustomTitle()
{
switch(Device.RuntimePlatform)
{
case Device.iOS:
{
PlainText = CustomTitle;
return;
}
case Device.Android:
{
Text = CustomTitle;
return;
}
default:
{
throw new NotSupportedException($"{Device.RuntimePlatform} not supported in {nameof(SetCustomTitle)}");
}
}
}
我在那里所做的是,我只是将 OnPlatform 代码移动到您的控件中,因此您可以保持 xaml 代码更干净。
使用这种方法,您应该能够像
<controls:CustomEditor HeightRequest="80" IsPassword="True" CustomTitle="{Binding KeyString}">
<controls:CustomEditor.Effects>
<controls:PasswordEffect/>
</controls:CustomEditor.Effects>
</controls:CustomEditor>
OnPlatform 的 x:TypeArguments 表示您要绑定的值类型,在您的情况下KeyString
类型为string
。看看平台。
<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>