C# 如何使用ReactiveList以便在添加新项时更新UI
我正在创建一个带有列表的Xamarin.Forms应用程序。itemSource是一个反应列表。但是,向列表中添加新项目不会更新UI。正确的做法是什么 列表定义C# 如何使用ReactiveList以便在添加新项时更新UI,c#,xamarin.forms,reactiveui,C#,Xamarin.forms,Reactiveui,我正在创建一个带有列表的Xamarin.Forms应用程序。itemSource是一个反应列表。但是,向列表中添加新项目不会更新UI。正确的做法是什么 列表定义 _listView = new ListView(); var cell = new DataTemplate(typeof(TextCell)); cell.SetBinding(TextCell.TextProperty, "name"); cell.SetBinding(TextCell.DetailProperty, "loca
_listView = new ListView();
var cell = new DataTemplate(typeof(TextCell));
cell.SetBinding(TextCell.TextProperty, "name");
cell.SetBinding(TextCell.DetailProperty, "location");
_listView.ItemTemplate = cell;
装订
this.OneWayBind(ViewModel, x => x.monkeys, x => x._listView.ItemsSource);
this.OneWayBind(ViewModel, x => x.save, x => x._button.Command); //save adds new items
视图模型
public class MyPageModel : ReactiveObject
{
public MyPageModel()
{
var canSave = this.WhenAny(x => x.username, x => !String.IsNullOrWhiteSpace(x.Value) && x.Value.Length>5);
save = ReactiveCommand.CreateAsyncTask(canSave, async _ =>
{
var monkey = new Monkey { name = username, location = "@ " + DateTime.Now.Ticks.ToString("X"), details = "More here" };
monkeys.Add(monkey);
username = "";
});
monkeys = new ReactiveList<Monkey>{
new Monkey { name="Baboon", location="Africa & Asia", details = "Baboons are Africian and Arabian Old World..." }
};
_monkeys.ChangeTrackingEnabled = true;
}
private string _username = "";
public string username
{
get { return _username; }
set { this.RaiseAndSetIfChanged(ref _username, value); }
}
private double _value = 0;
public double value
{
get { return _value; }
set { this.RaiseAndSetIfChanged(ref _value, value); }
}
public ReactiveCommand<Unit> save { get; set; }
public ReactiveList<Monkey> _monkeys;
public ReactiveList<Monkey> monkeys
{
get { return _monkeys; }
set { this.RaiseAndSetIfChanged(ref _monkeys, value); }
}
}
public class Monkey
{
public string name { get; set; }
public string location { get; set; }
public string details { get; set; }
}
尝试使用ReactiveList属性作为普通的auto属性,以及上面代码中我使用RaiseAndSetIfChanged方法时使用的属性。您的问题是在非UI线程上更改Monkey。在其他框架中,这会抛出一个异常,但在AppKit/UIKit中,这只是做一些奇怪的事情,通常什么都不做
save = ReactiveCommand.Create(canSave);
save.Subscribe(_ =>
{
// Do the part that modifies UI elements (or things bound to them)
// in the RxCmd's Subscribe. This is guaranteed to run on the UI thread
var monkey = new Monkey { name = username, location = "@ " + DateTime.Now.Ticks.ToString("X"), details = "More here" };
monkeys.Add(monkey);
username = "";
});
这项技术似乎非常复杂。这让我觉得你想做一些我认为更复杂的事情 这里有一个干净的解决方案,通过纯MVVM方式绑定到反应列表,将对象添加到列表框 首先是xaml
<Window x:Class="ReactiveUIListBox.View.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:viewModel="clr-namespace:ReactiveUIListBox.ViewModel"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<viewModel:MainWindowViewModel x:Key="MainWindowViewModel"/>
</Window.Resources>
<Window.DataContext>
<StaticResource ResourceKey="MainWindowViewModel"/>
</Window.DataContext>
<Grid DataContext="{StaticResource MainWindowViewModel}">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid Grid.Column="0" Background="Azure">
<ListBox ItemsSource="{Binding Model.TestReactiveList}"></ListBox>
</Grid>
<Grid Grid.Column="1">
<Button x:Name="button" Command="{Binding TestCommand}" Content="Button" HorizontalAlignment="Left" Margin="78,89,0,0" VerticalAlignment="Top" Width="75"/>
</Grid>
</Grid>
</Window>
这是ViewModel
using System.Windows.Input;
using ReactiveUIListBox.Model;
using SecretSauce.Mvvm.ViewModelBase;
namespace ReactiveUIListBox.ViewModel
{
public class MainWindowViewModel : ViewModelBase
{
public MainWindowViewModel()
{
Model = new ReactiveModel<string>();
}
public ReactiveModel<string> Model
{
get;
set;
}
public ICommand TestCommand
{
get { return new RelayCommand(ExecuteTestCommand); }
}
private void ExecuteTestCommand(object obj)
{
Model.TestReactiveList.Add("test string");
}
}
}
最后,这是模型
using ReactiveUI;
namespace ReactiveUIListBox.Model
{
public class ReactiveModel<T> : ReactiveObject
{
public ReactiveModel()
{
TestReactiveList= new ReactiveList<T>();
}
public ReactiveList<T> TestReactiveList
{
get;
set;
}
}
}
按下按钮将填充列表框。希望我没有完全简化您要做的事情,但是您的代码似乎到处都是
我无法区分适合视图、模型或视图模型的代码
干杯。我通过两个观察做出了上述改变。我必须将ReactiveCommand save更改为ReactiveCommand save才能编译代码。当我运行时,列表仍然不会更新,尽管当username属性设置为空字符串时,文本字段会清除。将列表的定义更改为public-ReactiveList-monkeys{get;set;},并具有相同的效果。更改为public-observeCollection-monkeys{get;set;}有效,ui刷新。我使用的反应列表是错误的吗?@ritcoder-你在这方面有什么进展吗?我仍然在一个Xam表单项目中遇到同样的问题。我不能使用ReactiveList,但对于测试项目,我正在进行的ObservableCollection已经足够了。上面的代码确实结构良好。基于以上内容,我的目标是能够动态生成ui。这是其中一个样本。不过我确实让它起作用了。等我拿到零钱,我会查出来的。