如何使用 ReactiveList 以便在添加新项目时更新 UI [英] How to use ReactiveList so UI is updated when new items are added

查看:38
本文介绍了如何使用 ReactiveList 以便在添加新项目时更新 UI的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在创建一个带有列表的 Xamarin.Forms 应用程序.itemSource 是一个reactiveList.但是,向列表中添加新项目不会更新 UI.这样做的正确方法是什么?

I'm creating a Xamarin.Forms application with a list. The itemSource is a reactiveList. Adding new items to the list however does not update the UI. What is the correct way of doing this?

列表定义

_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 属性作为一个普通的自动属性以及上面代码中我使用 RaiseAndSetIfChanged 方法的属性.

Tried it with the ReactiveList property being a normal auto-property as well as the one in the code above where I used the RaiseAndSetIfChanged method.

推荐答案

这种技术看起来非常复杂.这让我觉得你想做一些我认为更复杂的事情.

This technique seems awfully complicated. It makes me think that you want to do something more complicated that I think it to be.

这里有一个干净的解决方案,用于通过以纯 MVVM 方式绑定到 ReactiveList 来将对象添加到列表框.

Here's a clean solutionfor adding an object to a list box by binding to a ReactiveList<T> in pure MVVM fashion.

首先,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>

这是视图模型

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;
        }
    }
}

按下按钮将填充列表框.希望我没有完全简化您想要做的事情,但是您的代码似乎无处不在.

Pressing the button will populate the ListBox. Hopefully I have not completely over simplified what you are trying to do, but your code does seem to be all over the place.

我无法区分适合 View、Model 或 ViewModel 的代码.

I can't differentiate between your code that fits in the View, Model or ViewModel.

干杯.

这篇关于如何使用 ReactiveList 以便在添加新项目时更新 UI的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆