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 帮助我解决了这个问题。完整答案是:
- 将 Unit.Default select 语句移至油门后。
- 使用
Where
而不是 Select
来检查字符串是否为 NullOrWhiteSpace
.
- 将
WhenAnyValue
移动到创建 command
的位置之后。
- 最后使用 MainUIThread 从 ReactiveCommand 的 return 值设置公司。
我在我的一个 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 帮助我解决了这个问题。完整答案是:
- 将 Unit.Default select 语句移至油门后。
- 使用
Where
而不是Select
来检查字符串是否为NullOrWhiteSpace
. - 将
WhenAnyValue
移动到创建command
的位置之后。 - 最后使用 MainUIThread 从 ReactiveCommand 的 return 值设置公司。