Xamarin.Forms中DevExpress TextEdit无法绑定XCT UserStoppedTypingBehavior的问题
问题
在Xamarin.Forms应用中使用DevExpress Editor的TextEdit控件时,无法将其绑定到XCT的UserStoppedTypingBehavior,使用的代码如下:
<dxe:TextEdit Margin="2" LabelText="Evrak Seri" LabelFontSize="16" LabelColor="Black" IsVisible="{Binding EvrakSeriSiraGorunum}" BackgroundColor="White" BorderColor="Black" WidthRequest="300" Text="{Binding EvrakseriText}" ReserveBottomTextLine="True" IsLabelFloating="False" x:Name="evrakSeriText1" > <dxe:TextEdit.Behaviors> <xct:UserStoppedTypingBehavior Command="{Binding SearchCommand}" /> </dxe:TextEdit.Behaviors> <dxe:TextEdit.Triggers> <DataTrigger TargetType="dxe:TextEdit" Value="-1" Binding="{Binding Source={x:Reference evrakSeriText1}, Path=Text.Length}" > </DataTrigger> </dxe:TextEdit.Triggers> </dxe:TextEdit>
出现的错误:
System.InvalidOperationException Message=bindable not an instance of AssociatedType
怀疑是TargetType设置错误,但找不到正确类型。想知道TextEdit是否有类似XCT UserStoppedTypingBehavior的功能?如果没有,该如何解决这个问题?
解决方案
1. 错误根源
XCT的UserStoppedTypingBehavior是专为Xamarin.Forms原生Entry/Editor控件设计的,它的关联类型是原生Entry。而DevExpress的TextEdit是自定义控件,并非原生Entry的子类,直接挂载会触发类型不匹配的错误,也就是你看到的bindable not an instance of AssociatedType。
2. 使用TextEdit自带的事件实现等效功能
DevExpress的TextEdit本身没有现成的“停止输入触发命令”的内置行为,但可以通过TextChanged事件结合延迟执行来实现相同效果:
实现步骤:
- 在ViewModel中维护一个
CancellationTokenSource,用于取消未执行的延迟任务 - 每次文本变化时,取消之前的延迟任务,重新创建新的延迟任务(延迟时间可自定义,比如500ms)
- 延迟结束后执行你的
SearchCommand
示例代码:
ViewModel部分:
private CancellationTokenSource _typingCts; public ICommand SearchCommand { get; } public YourViewModel() { SearchCommand = new Command(ExecuteSearch); _typingCts = new CancellationTokenSource(); } private void OnTextChanged(string newText) { // 取消之前的延迟任务 _typingCts.Cancel(); _typingCts.Dispose(); _typingCts = new CancellationTokenSource(); // 延迟500ms后执行搜索命令 Task.Delay(500, _typingCts.Token) .ContinueWith(t => { if (!t.IsCanceled) { SearchCommand.Execute(null); } }, TaskScheduler.FromCurrentSynchronizationContext()); } private void ExecuteSearch() { // 你的搜索逻辑 }
XAML部分:
<dxe:TextEdit ... TextChanged="OnTextEditTextChanged" > </dxe:TextEdit>
Code-Behind部分:
private void OnTextEditTextChanged(object sender, DevExpress.XamarinForms.Editors.TextChangedEventArgs e) { var viewModel = BindingContext as YourViewModel; viewModel?.OnTextChanged(e.NewTextValue); }
3. 自定义适配TextEdit的行为(复用模式)
如果想沿用XCT行为的使用方式,可以自定义一个针对TextEdit的UserStoppedTypingBehavior:
public class TextEditUserStoppedTypingBehavior : Behavior<TextEdit> { public static readonly BindableProperty CommandProperty = BindableProperty.Create(nameof(Command), typeof(ICommand), typeof(TextEditUserStoppedTypingBehavior)); public static readonly BindableProperty StoppedDelayProperty = BindableProperty.Create(nameof(StoppedDelay), typeof(int), typeof(TextEditUserStoppedTypingBehavior), 500); private CancellationTokenSource _cts; public ICommand Command { get => (ICommand)GetValue(CommandProperty); set => SetValue(CommandProperty, value); } public int StoppedDelay { get => (int)GetValue(StoppedDelayProperty); set => SetValue(StoppedDelayProperty, value); } protected override void OnAttachedTo(TextEdit bindable) { base.OnAttachedTo(bindable); bindable.TextChanged += OnTextChanged; } protected override void OnDetachingFrom(TextEdit bindable) { base.OnDetachingFrom(bindable); bindable.TextChanged -= OnTextChanged; _cts?.Cancel(); } private void OnTextChanged(object sender, DevExpress.XamarinForms.Editors.TextChangedEventArgs e) { _cts?.Cancel(); _cts?.Dispose(); _cts = new CancellationTokenSource(); Task.Delay(StoppedDelay, _cts.Token) .ContinueWith(t => { if (!t.IsCanceled && Command != null && Command.CanExecute(null)) { Command.Execute(null); } }, TaskScheduler.FromCurrentSynchronizationContext()); } }
在XAML中使用这个自定义行为:
<dxe:TextEdit ... > <dxe:TextEdit.Behaviors> <local:TextEditUserStoppedTypingBehavior Command="{Binding SearchCommand}" StoppedDelay="500" /> </dxe:TextEdit.Behaviors> </dxe:TextEdit>
内容的提问来源于stack exchange,提问作者Mert Altiparmak
相关产品推荐
相关产品推荐

