【问题标题】:ReactiveUI Viewinjection. How to do it rightReactiveUI 视图注入。如何正确地做
【发布时间】:2017-01-19 10:08:47
【问题描述】:

我会尽可能详细地解释我的问题。我的应用程序是使用 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 会被处理掉吗?如果没有,我怎么能做到这一点? 我确定我错过了正确答案所需的一些部分,所以请询问,我会提供您需要的信息。

在此先感谢您的问候

【问题讨论】:

  • 我感觉你在这里用错了词。 Items get removed from the list when their itemsleft property reaches 0。你是说Senders get removed from the list when their itemsleft property reaches 0

标签: c# mvvm memory-leaks dispose reactiveui


【解决方案1】:

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

扩展方法是

    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()));

每当我的视图模型发生变化时,我都需要停止旧动画并开始一个新动画。最简单的方法是StartAnimation() 返回一个停止动画的IDisposableSubscribeDisposable 确保旧的IDisposable 在新的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 };
}

我希望这就是您想要的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-12
    • 1970-01-01
    • 2021-05-20
    • 1970-01-01
    • 1970-01-01
    • 2018-09-28
    • 2021-06-15
    • 1970-01-01
    相关资源
    最近更新 更多