InvokeCommand() 不触发

InvokeCommand() does not fire

我在我的一个 Xamarin.Forms 应用程序中使用 ReactiveUI。它具有 search 功能。就像 ReactiveUI Github 页面上的官方示例一样。但是 Search command 不会在 query 字符串更改时触发。我正在使用领域移动数据库进行本地存储。查看代码:

  <Shell.TitleView>
    <SearchBar x:Name="SearchHandler"
               Placeholder="Select Company" />
</Shell.TitleView>
<ContentPage.Content>

    <StackLayout>
        <ListView x:Name="CompaniesListView">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <ViewCell>
                        <StackLayout>
                            <StackLayout Orientation="Horizontal"
                                         Margin="10">
                                <Label x:Name="NameLabel"
                                       Text="{Binding Name}" />
                            </StackLayout>
                            <BoxView HorizontalOptions="FillAndExpand"
                                     HeightRequest="1"
                                     Color="BlueViolet" />
                        </StackLayout>
                    </ViewCell>
                </DataTemplate>

            </ListView.ItemTemplate>
            <ListView.Footer>
                <StackLayout Spacing="0"
                             HorizontalOptions="FillAndExpand">
                    <Frame CornerRadius="20"
                           Margin="10"
                           Padding="0">
                        <Entry Placeholder="Company Name"
                               x:Name="NewCompanyEntry"></Entry>
                    </Frame>

                    <Button Text="Add"
                            x:Name="AddButton"
                            HorizontalOptions="Center" />
                </StackLayout>
            </ListView.Footer>
        </ListView>

    </StackLayout>

</ContentPage.Content>

背后的代码:

   public partial class MainPage : ReactiveContentPage<MainViewModel>
{


    public MainPage()
    {
        InitializeComponent();

        ViewModel = new MainViewModel();


        this.Bind(ViewModel, vm => vm.Query, v => v.SearchHandler.Text);
        this.BindCommand(ViewModel, vm => vm.AddCompanyCommand, v => v.AddButton);
        this.Bind(ViewModel, vm => vm.NewCompany, v => v.NewCompanyEntry.Text);
        this.OneWayBind(ViewModel, vm => vm.Companies, view => view.CompaniesListView.ItemsSource);


    }
}

视图模型:

 public class MainViewModel : ReactiveObject
{

    public IEnumerable<Company> Companies { get; set; }


    [Reactive]
    public string Query { get; set; }

    [Reactive]
    public string NewCompany { get; set; }

    public ReactiveCommand<Unit, Unit> AddCompanyCommand { get; set; }
    public ReactiveCommand<Unit, Unit> Search { get; set; }

    Realm _realm;

    public MainViewModel()
    {

        _realm = Realm.GetInstance();
        Companies = _realm.All<Company>();

        this.WhenAnyValue(x => x.Query).Select(query => !String.IsNullOrWhiteSpace(query)).Select(_ => Unit.Default).Throttle(TimeSpan.FromSeconds(1)).InvokeCommand(this, x => x.Search);

        AddCompanyCommand = ReactiveCommand.CreateFromTask(async () => await AddButtonClicked());
        Search = ReactiveCommand.CreateFromObservable(
            () =>
               Observable
               .StartAsync(SortCollection)
        );
    }



    async Task AddButtonClicked()
    {
        if (!string.IsNullOrWhiteSpace(NewCompany))
        {
            _realm.Write(() =>
            {
                _realm.Add(new Company { Name = NewCompany });
            });
            NewCompany = string.Empty;
        }
    }

    async Task SortCollection()
    {

        Companies = _realm.All<Company>().OrderBy(m => m.Name).Where(company => company.Name.ToLower().Contains(Query.ToLower()));

    }
}

这个 demo 应用程序也可以在我的 GitHub profile 上使用。

谢谢。

this.WhenAnyValue(x => x.Query).Select(query => !String.IsNullOrWhiteSpace(query)).Select(_ => Unit.Default).Throttle(TimeSpan.FromSeconds(1)).InvokeCommand(this, x => x.Search);

这一行可能是问题所在。 Throttle returns 一个经过时间的值。将 Unit.Default select 语句移到它后面。

Glenn Watson 的回答并不完整。尽管他通过评论和 slack 帮助我解决了这个问题。完整答案是:

  1. 将 Unit.Default select 语句移至油门后。
  2. 使用 Where 而不是 Select 来检查字符串是否为 NullOrWhiteSpace.
  3. WhenAnyValue 移动到创建 command 的位置之后。
  4. 最后使用 MainUIThread 从 ReactiveCommand 的 return 值设置公司。