ReactiveTableViewSource<TSource> 是如何工作的?
How does ReactiveTableViewSource<TSource> work?
在我们的应用中,我们使用 ReactiveUI 来遵循 MVVM 模式。在一个视图中,我们想显示一个 UITableView。数据通常传递给 UITableView.Source 但对于 ReactiveUI 我们使用 ReactiveTableViewSource<TSource>
.
我不明白的是如何将我在 ReactiveList
中的视图模型中获得的数据绑定到 ReactiveTableViewSource
。
我们现在拥有的是在 UI 视图中创建一个 table,如下所示:
Table = new UITableView(UIScreen.MainScreen.Bounds);
Table.Source = new TableSource(Table, MyReactiveList, (NSString) CellIdentifier, _cellHeight, cell => Debug.WriteLine(cell));
顺便说一句:单元格操作的用途是什么?
此外,我们还有一个 Table 来源 class,如下所示:
internal sealed class TableSource : ReactiveTableViewSource<MyListObject>
{
public TableSource(UITableView tableView, IReactiveNotifyCollectionChanged<MyListObject> collection, NSString cellKey, float sizeHint, Action<UITableViewCell> initializeCellAction = null) : base(tableView, collection, cellKey, sizeHint, initializeCellAction)
在我的视图模型中,我有一个正在更新我的 ReactiveList 的服务。它看起来像这样:
public sealed class MyService : ReactiveObject, IMyService
{
public IReactiveList<MyListObject> MyReactiveList { get; }
public async Task UpdateMyReactiveListAsync() {//...}
我在哪里将 table 源绑定到 ReactiveList?我在哪里订阅活动?是否有任何我可能遗漏的文档或示例代码?
要订阅事件,您可以分配一个 UITableViewDelegateRx
var tvd = new UITableViewDelegateRx ();
Table.Delegate = tvd;
tvd.RowSelectedObs.Subscribe (c => { });
使用 ReactiveTableViewSource 非常简单:
只需将 List 与您的 UITableView 连接起来
var tableView = new UITableView ();
// Bind the List agains the table view
// SampleObject is our model and SampleCell the cell
ViewModel.WhenAnyValue (vm => vm.Items).BindTo<SampleObject, SampleCell> (tableView, 46, cell => cell.Initialize());
然后创建一个自定义单元格,您可以在其中将模型数据绑定到单元格。
public class SampleCell : ReactiveTableViewCell, IViewFor<SampleObject>
{
public SampleCell () : base() { }
public SampleCell (IntPtr handle) : base(handle) { }
private SampleObject _viewModel;
public SampleObject ViewModel
{
get { return _viewModel; }
set { this.RaiseAndSetIfChanged (ref _viewModel, value); }
}
object IViewFor.ViewModel
{
get { return ViewModel; }
set { ViewModel = value as SampleObject; }
}
public void Initialize()
{
this.WhenAnyValue (v => v.ViewModel.Name).BindTo (
this,
v => v.TextLabel.Text);
}
}
您可以在此处找到一个引人注目的示例:https://github.com/reicheltp/ReactiveTableViewSource-Sample
2016/03/09 更新:最好在单独的 Initialize 方法中进行绑定,以防止多次调用。
如果你有更多问题可以在推特上问我:@reicheltp
只是为了使用 ReactiveUI 版本 9.16.6 进行小更新:
示例列出了一些城市及其相应的邮政编码。
- => 我的 ViewController 继承自 ReactiveViewController
- => 我的 CityViewModel 继承自 ReactiveObject
- => 我的 CityItemViewModel 继承自 ReactiveObject
=> 我的 CityTableViewCell 继承自 ReactiveTableViewCell
public class CityViewModel : ReactiveObject
{
private ICityService CityService { get; }
private SourceCache<CityItemViewModel, int> _citiesCache;
private IObservable<IChangeSet<CityItemViewModel, int>> _citiesOperations => _citiesCache.Connect();
public readonly ReadOnlyObservableCollection<CityItemViewModel> Cities;
public CityViewModel(ICityService cityService)
{
CityService = cityService;
}
#region CityViewModelCommand
public ReactiveCommand<CityItemViewModel, Unit> CityClickCommand { get; }
#endregion
private async Task<IEnumerable<CityItemViewModel>> SearchCitiesAsync(string searchText, CancellationToken token)
{
IEnumerable<CityItemViewModel> items;
if (string.IsNullOrEmpty(searchText))
items = await CityService.ToListWithCountryCodeAsync(cancellationToken: token);
else
items = await CityService.ToListBySearchWithCountryCodeAsync(searchText, cancellationToken: token);
_citiesCache.Edit(innerList =>
{
innerList.Clear();
innerList.AddOrUpdate(items);
});
return items;
}
}
public class CityItemViewModel : ReactiveObject
{
public int Id { get; set; }
public string Name { get; set; }
public string PostalCode { get; set; }
public override string ToString()
=> $"[CityItemViewModel: Id={Id}, Name={Name}, PostalCode={PostalCode}]";
public CityItemViewModel() : base()
{
}
}
在我的 ViewController 的 ViewDidLoad 方法中:
this.WhenActivated((cleanup) =>
{
this.Bind(ViewModel,
x => x.SearchText,
x => x.searchBar.Text)
.DisposeWith(cleanup);
this.WhenAnyValue(v => v.ViewModel.Cities)
.BindTo<CityItemViewModel, CityTableViewCell>(tableView, CityTableViewCell.Key, 50, cell => cell.Initialize(),
source => source.ElementSelected.InvokeCommand(ViewModel.CityClickCommand))
.DisposeWith(cleanup);
});
在我的 UITableViewCell 的 Initialize 方法中:
public void Initialize()
{
this.WhenAnyValue(v => v.ViewModel.Name)
.Subscribe(name => cityLabel.Text = name);
this.WhenAnyValue(v => v.ViewModel.PostalCode)
.Subscribe(x => postalCodeLabel.Text = x);
}
希望能帮到别人 ;)
在我们的应用中,我们使用 ReactiveUI 来遵循 MVVM 模式。在一个视图中,我们想显示一个 UITableView。数据通常传递给 UITableView.Source 但对于 ReactiveUI 我们使用 ReactiveTableViewSource<TSource>
.
我不明白的是如何将我在 ReactiveList
中的视图模型中获得的数据绑定到 ReactiveTableViewSource
。
我们现在拥有的是在 UI 视图中创建一个 table,如下所示:
Table = new UITableView(UIScreen.MainScreen.Bounds);
Table.Source = new TableSource(Table, MyReactiveList, (NSString) CellIdentifier, _cellHeight, cell => Debug.WriteLine(cell));
顺便说一句:单元格操作的用途是什么?
此外,我们还有一个 Table 来源 class,如下所示:
internal sealed class TableSource : ReactiveTableViewSource<MyListObject>
{
public TableSource(UITableView tableView, IReactiveNotifyCollectionChanged<MyListObject> collection, NSString cellKey, float sizeHint, Action<UITableViewCell> initializeCellAction = null) : base(tableView, collection, cellKey, sizeHint, initializeCellAction)
在我的视图模型中,我有一个正在更新我的 ReactiveList 的服务。它看起来像这样:
public sealed class MyService : ReactiveObject, IMyService
{
public IReactiveList<MyListObject> MyReactiveList { get; }
public async Task UpdateMyReactiveListAsync() {//...}
我在哪里将 table 源绑定到 ReactiveList?我在哪里订阅活动?是否有任何我可能遗漏的文档或示例代码?
要订阅事件,您可以分配一个 UITableViewDelegateRx
var tvd = new UITableViewDelegateRx ();
Table.Delegate = tvd;
tvd.RowSelectedObs.Subscribe (c => { });
使用 ReactiveTableViewSource 非常简单:
只需将 List 与您的 UITableView 连接起来
var tableView = new UITableView ();
// Bind the List agains the table view
// SampleObject is our model and SampleCell the cell
ViewModel.WhenAnyValue (vm => vm.Items).BindTo<SampleObject, SampleCell> (tableView, 46, cell => cell.Initialize());
然后创建一个自定义单元格,您可以在其中将模型数据绑定到单元格。
public class SampleCell : ReactiveTableViewCell, IViewFor<SampleObject>
{
public SampleCell () : base() { }
public SampleCell (IntPtr handle) : base(handle) { }
private SampleObject _viewModel;
public SampleObject ViewModel
{
get { return _viewModel; }
set { this.RaiseAndSetIfChanged (ref _viewModel, value); }
}
object IViewFor.ViewModel
{
get { return ViewModel; }
set { ViewModel = value as SampleObject; }
}
public void Initialize()
{
this.WhenAnyValue (v => v.ViewModel.Name).BindTo (
this,
v => v.TextLabel.Text);
}
}
您可以在此处找到一个引人注目的示例:https://github.com/reicheltp/ReactiveTableViewSource-Sample
2016/03/09 更新:最好在单独的 Initialize 方法中进行绑定,以防止多次调用。
如果你有更多问题可以在推特上问我:@reicheltp
只是为了使用 ReactiveUI 版本 9.16.6 进行小更新:
示例列出了一些城市及其相应的邮政编码。
- => 我的 ViewController 继承自 ReactiveViewController
- => 我的 CityViewModel 继承自 ReactiveObject
- => 我的 CityItemViewModel 继承自 ReactiveObject
=> 我的 CityTableViewCell 继承自 ReactiveTableViewCell
public class CityViewModel : ReactiveObject { private ICityService CityService { get; } private SourceCache<CityItemViewModel, int> _citiesCache; private IObservable<IChangeSet<CityItemViewModel, int>> _citiesOperations => _citiesCache.Connect(); public readonly ReadOnlyObservableCollection<CityItemViewModel> Cities; public CityViewModel(ICityService cityService) { CityService = cityService; } #region CityViewModelCommand public ReactiveCommand<CityItemViewModel, Unit> CityClickCommand { get; } #endregion private async Task<IEnumerable<CityItemViewModel>> SearchCitiesAsync(string searchText, CancellationToken token) { IEnumerable<CityItemViewModel> items; if (string.IsNullOrEmpty(searchText)) items = await CityService.ToListWithCountryCodeAsync(cancellationToken: token); else items = await CityService.ToListBySearchWithCountryCodeAsync(searchText, cancellationToken: token); _citiesCache.Edit(innerList => { innerList.Clear(); innerList.AddOrUpdate(items); }); return items; } } public class CityItemViewModel : ReactiveObject { public int Id { get; set; } public string Name { get; set; } public string PostalCode { get; set; } public override string ToString() => $"[CityItemViewModel: Id={Id}, Name={Name}, PostalCode={PostalCode}]"; public CityItemViewModel() : base() { } }
在我的 ViewController 的 ViewDidLoad 方法中:
this.WhenActivated((cleanup) =>
{
this.Bind(ViewModel,
x => x.SearchText,
x => x.searchBar.Text)
.DisposeWith(cleanup);
this.WhenAnyValue(v => v.ViewModel.Cities)
.BindTo<CityItemViewModel, CityTableViewCell>(tableView, CityTableViewCell.Key, 50, cell => cell.Initialize(),
source => source.ElementSelected.InvokeCommand(ViewModel.CityClickCommand))
.DisposeWith(cleanup);
});
在我的 UITableViewCell 的 Initialize 方法中:
public void Initialize()
{
this.WhenAnyValue(v => v.ViewModel.Name)
.Subscribe(name => cityLabel.Text = name);
this.WhenAnyValue(v => v.ViewModel.PostalCode)
.Subscribe(x => postalCodeLabel.Text = x);
}
希望能帮到别人 ;)