ReactiveUI Viewinjection。怎么做对

时间:2017-01-19 10:08:47

标签: c# mvvm memory-leaks dispose reactiveui

我会尽可能详细地解释我的问题。我的应用程序是使用mvvm编写的,并且有一个shellview,它可以加载一些静态视图。继承人问题1: 在shellviewmodel中实例化这些视图模型是一个好习惯吗?

public ShellViewModel(IScreen screen)
    {
        HostScreen = screen;


        LogoViewModel = new LogoViewModel(HostScreen);
        ...
        StatusViewModel = new StatusViewModel();

    }

无论如何我还有一个静态视图,它有一个列表,其ItemSource属性绑定到ReactiveList

     public ShiftOrderView()//ShiftOrderViewModel viewModel)
            {
                InitializeComponent();

                this.WhenActivated(
                    d =>
                        {
                            this.OneWayBind(ViewModel, vm => vm.ProductionOrderList, v => v.ShiftOrder.ItemsSource).AddTo(d);
    });
}

现在每当用户选择新的列表项时,此项目将显示在另一个视图中。我目前正在通过导航

这样做
        this.WhenActivated(d =>
        {
            this.WhenAnyObservable(o => o.ProductionOrderList.ItemChanged)
                .Where(x => x.PropertyName == "ItemsLeft")
                .Select(x => x.Sender)
                .Where(x => x.ItemsLeft == 0)
                .Subscribe(x =>
                {

                    ProductionOrderList.Remove(x);
                }).AddTo(d);

            this.WhenAnyValue(vm => vm.SelectedProductionOrderViewModel).Where(pvm => pvm != null)
                .Subscribe(pvm =>
                {
                    HostScreen.Router.NavigateAndReset.Execute(
                        new ProductionOrderDetailViewModel(HostScreen,
                        Locator.CurrentMutable.GetService<IProductionItemService>(), pvm));
                }).AddTo(d);

        });

但我认为这不是正确的方法,并引入内存泄漏。正如您在上面的代码中看到的,当itemsleft属性达到0时,项目将从列表中删除。但我不确定如何正确处理这些项目。如果我在导航方法中创建一个新实例,旧的新ProductionOrderDetailViewModel会被处理掉吗?如果不是我怎么能实现这一目标? 我确信我错过了正确答案所需的一些部分,所以请询问,我将提供您需要的信息。

提前致谢并致以亲切的问候

1 个答案:

答案 0 :(得分:0)

我想我看到了你遇到的问题模式,我认识到了这一点。您有一个T : IDisposable类型的属性,当该属性更新时,您希望处置旧版本。我有IObservable<T>的扩展方法,它将以一般方式解决此类问题。

扩展方法是

    public static IDisposable SubscribeDisposable<T>
        (this IObservable<T> observable, Func<T, IDisposable> action)
    {
        var d = new SerialDisposable();
        return observable
            .Finally(() => d.Dispose())
            .Subscribe(e =>
            {
                d.Disposable = Disposable.Empty;
                d.Disposable = action(e);
            });
    }

你可以像

一样使用它
this
  .WhenAnyValue(p=>p.DisposableProperty)
  .SubscribeDisposable(v=>v)
  .AddTo(d);

但通常我会在SubscribeDisposable中添加更复杂的内容。例如,在我的一些代码中,我有

 this.LoadUnloadHandler(() => this
                .WhenAnyValue(p => p.ViewModel)
                .WhereNotNull()
                .SubscribeDisposable(x=>x.StartAnimation()));

每当我的viewmodel发生变化时,我都需要停止旧动画并开始一个新动画。最简单的方法是StartAnimation()返回停止动画的IDisposableSubscribeDisposable确保在创建新IDisposable之前处置旧StartAnimation,从而对动画进行整齐排序。

为了清楚起见public IDisposable StartAnimation() { return Animation = new PlayController( maximum: 2 * Math.PI, minSpeed: Math.PI / 180 * 10, maxSpeed: 2 * Math.PI, currentSpeed: Math.PI, jogAmount: Math.PI / 50, fps: 120, modes: new Dictionary<AnimationMode, string> { { AnimationMode.PlayOnce, "Play once" }, { AnimationMode.PlayAndReverse, "Play and reverse" }, { AnimationMode.Loop, "Loop" } }) { StickyWidth = 50 }; } 方法。

public interface CrudRepository<T, ID extends Serializable>
extends Repository<T, ID> {

    <S extends T> S save(S entity);

    T findOne(ID primaryKey);

    Iterable<T> findAll();

    Long count();

    void delete(T entity);

    boolean exists(ID primaryKey);

    // … more functionality omitted.
}

我希望这就是你要找的东西。