Reactive UI实现带500ms延迟的自定义搜索控件问题求助
问题分析与修正方案
错误原因
- SearchBar自带命令触发冲突:XAML中SearchBar的
SearchCommand直接绑定到了控件的SearchCommand,SearchBar自身会在输入字符、点击搜索按钮等时机直接执行该命令,完全绕过了你用ReactiveUI实现的500ms延迟逻辑。 - 订阅时机错误:构造函数中先执行ReactiveUI的订阅逻辑,再调用
InitializeComponent(),会导致XAML初始化时Text的初始绑定值触发一次订阅执行,引发不必要的搜索。
修正步骤
1. 修改XAML代码
移除SearchBar的SearchCommand绑定,完全通过ReactiveUI的延迟逻辑触发搜索:
<?xml version="1.0" encoding="UTF-8" ?> <yummy:PancakeView x:Class="Endeavor.App.Mobile.Controls.SearchControlWithDelay" xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:effects="clr-namespace:Endeavor.App.Mobile.Effects" xmlns:i18n="clr-namespace:JEndeavor.App.Mobile.Resources" xmlns:yummy="clr-namespace:Xamarin.Forms.PancakeView;assembly=Xamarin.Forms.PancakeView" x:Name="control" Padding="0" BackgroundColor="White" CornerRadius="20" VerticalOptions="Center" AutomationId="searchControlView"> <SearchBar x:Name="searchBar" AutomationId="searchBar" BackgroundColor="White" HeightRequest="50" Placeholder="{x:Static i18n:Translator.Header_Search}" Text="{x:Binding Source={x:Reference control}, Path=Text, Mode=TwoWay}"> <SearchBar.Effects> <effects:SearchBarBackgroundEffect /> </SearchBar.Effects> </SearchBar> </yummy:PancakeView>
2. 修正后台代码
- 调整
InitializeComponent()位置,先初始化XAML再订阅,避免初始值触发无效搜索 - 增加订阅释放逻辑,避免内存泄漏
- 加入命令可执行状态判断,符合ICommand规范:
using System; using System.Reactive.Linq; using System.Windows.Input; using Xamarin.Forms; using Xamarin.Forms.PancakeView; using Xamarin.Forms.Xaml; namespace Endeavor.App.Mobile.Controls { [XamlCompilation(XamlCompilationOptions.Compile)] public partial class SearchControlWithDelay : PancakeView { private IDisposable searchPredicate; public static BindableProperty TextProperty = BindableProperty.Create(nameof(Text), typeof(string), typeof(SearchControlWithDelay), null, BindingMode.TwoWay); public static BindableProperty SearchCommandProperty = BindableProperty.Create(nameof(SearchCommand), typeof(ICommand), typeof(SearchControlWithDelay), null); public ICommand SearchCommand { get { return (ICommand)GetValue(SearchCommandProperty); } set { SetValue(SearchCommandProperty, value); } } public string Text { get { return (string)GetValue(TextProperty); } set { SetValue(TextProperty, value); } } public SearchControlWithDelay() { InitializeComponent(); searchPredicate = this.WhenAnyValue(x => x.Text) .Throttle(TimeSpan.FromMilliseconds(500), RxApp.MainThreadScheduler) .DistinctUntilChanged() .Where(x => !string.IsNullOrWhiteSpace(x)) .Subscribe(x => { if (SearchCommand?.CanExecute(x) ?? false) { SearchCommand.Execute(x); } }); } protected override void OnDisappearing() { base.OnDisappearing(); searchPredicate?.Dispose(); } } }
额外优化说明
Where(x => !string.IsNullOrWhiteSpace(x)):过滤空字符串或纯空白字符的搜索请求CanExecute判断:确保命令在可执行状态下才执行,遵循ICommand设计规范
内容的提问来源于stack exchange,提问作者Endeavor
相关产品推荐
相关产品推荐

