C# 如何在Xamarin表单的编辑器中实现占位符?
我读到编辑器控件没有占位符,所以我一直在尝试解决方法,但没有成功。我知道条目控件有一个占位符,但我需要多行字段,因为我将使用它作为一个字段,用户可以在其中编写注释,而不仅仅是一行 这是我的方法: 我尝试将编辑器和标签放入网格控件中,标签位于编辑器的顶部。编辑器的C# 如何在Xamarin表单的编辑器中实现占位符?,c#,xamarin,mvvm,xamarin.forms,C#,Xamarin,Mvvm,Xamarin.forms,我读到编辑器控件没有占位符,所以我一直在尝试解决方法,但没有成功。我知道条目控件有一个占位符,但我需要多行字段,因为我将使用它作为一个字段,用户可以在其中编写注释,而不仅仅是一行 这是我的方法: 我尝试将编辑器和标签放入网格控件中,标签位于编辑器的顶部。编辑器的InputTransparent标志设置为true。然后,根据编辑器是否有文本,我只需切换标签的IsVisible属性。但是,问题是我使用的是MVVM模式,因此我不知道如何控制ViewModel中的TextChanged事件。我也尝试过代
InputTransparent
标志设置为true
。然后,根据编辑器是否有文本,我只需切换标签的IsVisible
属性。但是,问题是我使用的是MVVM模式,因此我不知道如何控制ViewModel
中的TextChanged
事件。我也尝试过代码隐藏,但是找不到标签的名称
这是我的XAML代码-我只发布了相关代码:
<Grid Grid.Row="1">
<Editor Text="{Binding UserComment, Mode=TwoWay}" TextChanged="EditorTextChanged" HorizontalOptions="FillAndExpand"/>
<Label x:Name="PlaceholderLabel" Text="Write a comment" InputTransparent="True" HorizontalOptions="StartAndExpand"/>
</Grid>
您要寻找的是自定义呈现程序,因为Xamarin.Forms只是本机元素的另一个级别,所以您可以使用自定义呈现程序“访问”本机元素:
您可以创建基本自定义编辑器:
using Xamarin.Forms;
namespace EditorWithPlaceholder
{
public class PlaceholderEditor : Editor
{
public static BindableProperty PlaceholderProperty
= BindableProperty.Create(nameof(Placeholder), typeof(string), typeof(PlaceholderEditor));
public static BindableProperty PlaceholderColorProperty
= BindableProperty.Create(nameof(PlaceholderColor), typeof(Color), typeof(PlaceholderEditor), Color.Gray);
public string Placeholder
{
get { return (string) GetValue(PlaceholderProperty); }
set { SetValue(PlaceholderProperty, value); }
}
public Color PlaceholderColor
{
get { return (Color) GetValue(PlaceholderColorProperty); }
set { SetValue(PlaceholderColorProperty, value); }
}
}
}
以及每个平台上的渲染器:
安卓:
using Xamarin.Forms;
using Xamarin.Forms.Platform.Android;
[assembly: ExportRenderer(typeof(PlaceholderEditor), typeof(PlaceholderEditorRenderer))]
namespace EditorWithPlaceholder.Droid.Renderers
{
public class PlacehoderEditorRenderer : EditorRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
{
base.OnElementChanged(e);
if (Element == null)
return;
var element = (PlaceholderEditor) Element;
Control.Hint = element.Placeholder;
Control.SetHintTextColor(element.PlaceholderColor.ToAndroid());
}
}
}
使用Xamarin.Forms;
使用Xamarin.Forms.Platform.Android;
[程序集:导出渲染器(类型化(占位符编辑器)、类型化(占位符编辑器或渲染器))]
命名空间编辑器WithPlaceholder.Droid.Renderers
{
公共类PlacehoderEditorRenderer:EditorRenderer
{
受保护的覆盖无效OnElementChanged(ElementChangedEventArgs e)
{
基础。一个要素发生变化(e);
if(元素==null)
返回;
var元素=(占位符编辑器)元素;
Control.Hint=element.Placeholder;
Control.SetHintTextColor(element.placeholder.ToAndroid());
}
}
}
iOS:
使用系统;
使用cirrium.FluentLayouts.Touch;
使用基础;
使用UIKit;
使用Xamarin.Forms;
使用Xamarin.Forms.Platform.iOS;
[程序集:导出渲染器(类型化(占位符编辑器)、类型化(占位符编辑器或渲染器))]
命名空间编辑器WithPlaceholder.iOS.Renders
{
公共类占位符EditorRenderer:EditorRenderer
{
专用UILabel _占位符标签;
受保护的覆盖无效OnElementChanged(ElementChangedEventArgs e)
{
基础。一个要素发生变化(e);
if(元素==null)
返回;
CreatePlaceholderLabel((占位符编辑器)元素,控件);
控制。结束+=结束;
Control.TextChanged+=OnChanged;
}
私有void CreatePlaceholderLabel(占位符编辑器元素,UITextView父元素)
{
_占位符标签=新UILabel
{
Text=元素。占位符,
TextColor=element.placeholder.ToUIColor(),
BackgroundColor=UIColor.Clear,
Font=UIFont.FromName(element.FontFamily,(nfloat)element.FontSize)
};
_Placeholder Label.SizeToFit();
parent.AddSubview(\u占位符标签);
parent.subviewsdonottranslationautoresizingmaskintoconstraints();
parent.AddConstraints(
_Placeholder Label.AtLeftOf(父项,7),
_占位符标签。带占位符中心(父项)
);
parent.layoutifneed();
_占位符label.Hidden=parent.HasText;
}
私有void onned(对象发送方、事件args args)
{
if(!((UITextView)sender).HasText&&u占位符标签!=null)
_占位符label.Hidden=false;
}
私有void OnChanged(对象发送方、事件args args)
{
如果(_占位符标签!=null)
_占位符label.Hidden=((UITextView)sender.HasText;
}
受保护的覆盖无效处置(布尔处置)
{
如果(处置)
{
控制。结束-=未结束;
Control.Changed-=OnChanged;
_占位符标签?.Dispose();
_占位符标签=空;
}
基地。处置(处置);
}
}
}
我希望这些信息有帮助
供参考:
以下是您自己提到的行之有效的方法:
<AbsoluteLayout
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<Editor
Text="{Binding Address, Mode=TwoWay}"
HorizontalOptions="FillAndExpand"
AbsoluteLayout.LayoutFlags="PositionProportional, WidthProportional"
AbsoluteLayout.LayoutBounds="0,0,1.01,100">
</Editor>
<Label Text="MyPlaceHolder" IsVisible="{Binding IsAddrerssPlaceHolderVisible}" HorizontalTextAlignment="Center"
AbsoluteLayout.LayoutBounds="0.5,0.5, 1, 0.5" VerticalTextAlignment="Center"
AbsoluteLayout.LayoutFlags="All" InputTransparent="True"/>
</AbsoluteLayout>
它甚至不需要我之前错误提到的任何东西!它的工作原理很简单:D我已经在MVVM中成功地实现了您的方法。您可以将任何事件转换为要从viewmodel运行的命令,为此,您可以使用行为NuGet。@Vahid您可以演示如何执行吗?:)我已经试过了,但是我的代码有点问题。出于某种原因,它不会使标签不可见,即使当它通过isAddressSplaceHolderVible=false;时也是如此;。我已经用一个断点进行了测试,这正是我在自己的项目中使用的断点,它工作起来很有魅力。您是否已将PropertyChanged通知程序事件放置在IsAddressSplaceHoldService的setter中,如上面的代码中所示,它是“RaisePropertyChanged()”?请显示您的IsAddressSplaceHoldService属性。是的,这里:private bool\u labelIsVisible{get;set;}=true;public bool LabelIsVisible{get{return{u LabelIsVisible;}set{{u LabelIsVisible=value;OnPropertyChanged(nameof(LabelIsVisible));}
我还尝试在代码中将LabelIsVisible设置为false时打印它。它说的是假的,但这并不能让它隐形。
using System;
using Cirrious.FluentLayouts.Touch;
using Foundation;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
[assembly: ExportRenderer(typeof(PlaceholderEditor), typeof(PlaceholderEditorRenderer))]
namespace EditorWithPlaceholder.iOS.Renderers
{
public class PlaceholderEditorRenderer : EditorRenderer
{
private UILabel _placeholderLabel;
protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
{
base.OnElementChanged(e);
if (Element == null)
return;
CreatePlaceholderLabel((PlaceholderEditor) Element, Control);
Control.Ended += OnEnded;
Control.TextChanged += OnChanged;
}
private void CreatePlaceholderLabel(PlaceholderEditor element, UITextView parent)
{
_placeholderLabel = new UILabel
{
Text = element.Placeholder,
TextColor = element.PlaceholderColor.ToUIColor(),
BackgroundColor = UIColor.Clear,
Font = UIFont.FromName(element.FontFamily, (nfloat)element.FontSize)
};
_placeholderLabel.SizeToFit();
parent.AddSubview(_placeholderLabel);
parent.SubviewsDoNotTranslateAutoresizingMaskIntoConstraints();
parent.AddConstraints(
_placeholderLabel.AtLeftOf(parent, 7),
_placeholderLabel.WithSameCenterY(parent)
);
parent.LayoutIfNeeded();
_placeholderLabel.Hidden = parent.HasText;
}
private void OnEnded(object sender, EventArgs args)
{
if (!((UITextView) sender).HasText && _placeholderLabel != null)
_placeholderLabel.Hidden = false;
}
private void OnChanged(object sender, EventArgs args)
{
if (_placeholderLabel != null)
_placeholderLabel.Hidden = ((UITextView) sender).HasText;
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
Control.Ended -= OnEnded;
Control.Changed -= OnChanged;
_placeholderLabel?.Dispose();
_placeholderLabel = null;
}
base.Dispose(disposing);
}
}
}
<AbsoluteLayout
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<Editor
Text="{Binding Address, Mode=TwoWay}"
HorizontalOptions="FillAndExpand"
AbsoluteLayout.LayoutFlags="PositionProportional, WidthProportional"
AbsoluteLayout.LayoutBounds="0,0,1.01,100">
</Editor>
<Label Text="MyPlaceHolder" IsVisible="{Binding IsAddrerssPlaceHolderVisible}" HorizontalTextAlignment="Center"
AbsoluteLayout.LayoutBounds="0.5,0.5, 1, 0.5" VerticalTextAlignment="Center"
AbsoluteLayout.LayoutFlags="All" InputTransparent="True"/>
</AbsoluteLayout>
public bool IsAddrerssPlaceHolderVisible
{
get => _isAddrerssPlaceHolderVisible;
set
{
_isAddrerssPlaceHolderVisible= value;
RaisePropertyChanged();
}
}
public string Address
{
get => _address;
set
{
_address = value;
if (value.Length > 0)
{
IsAddrerssPlaceHolderVisible= false;
}
else
{
IsAddrerssPlaceHolderVisible= true;
}
RaisePropertyChanged();
}
}