是否可以创建一个ReactiveUI派生集合,其中包含的元素多于原始集合?
我已经看到有一种过滤集合和选择单个属性的方法,但我正在寻找的是相当于枚举的SelectMany操作.
为了说明这一点,想象一下,试图获得一个派生的集合,代表每个遇阻交通堵塞的乘客
class Car
{
ReactiveCollection<Passenger> Passengers;
}
var TrafficJam=new ReactiveCollection<Car>();
EveryPassengerInTheTrafficJam=Cars.CreateDerivedCollection(c=>c.Passengers);
Run Code Online (Sandbox Code Playgroud)
以上不起作用,我认为无论如何IEnumerable<ReactiveCollection<Passenger>>都不能将错误转换为ReactiveCollection<Passenger>- 或类型的东西.
我无法弄清楚这种扁平化的正确方法 - 不可否认,我可能会在这里完全错误地咆哮,所以请告诉我是否有更好的方法来实现同样的目标!
当我没有在Observer上显式调用Dispose时,我很好奇ObservableForProperty生命周期.在这种情况下,我并不关心如何获得订阅太长时间等.
在传统的.NET中如果你有事件,除非你取消订阅它可能会导致内存泄漏,因为你的对象生命周期绑定到事件.例如,如http://msdn.microsoft.com/en-us/magazine/cc163316.aspx中所述:
事件也可以是强根引用,因此可以有助于强引用路径,从而影响对象的生命周期.公共语言运行时(CLR)2.0中的普通事件是事件源和侦听器之间的双向强引用,因此可以使对象(源或侦听器)保持活动,否则应该已经死亡.
在遇到INotifyPropertyChanged对象时查看ReactiveUI代码库,我注意到您正在使用FromEventPattern订阅INotifyPropertyChange事件.
使用ObservableForProperty是否可以解决这个问题,即通过创建强引用路径来保持对象的存活时间更长?
谢谢,格伦
最近我试图让自己进入UI开发的新时代并发现了ReactiveUI.我喜欢它的陈述性.
我想做一个完整的切换,所以我试着理解在ReactiveUI的这个新世界里是如何做出的.我选择了ReactiveUI,因为我看到它是由一个非常聪明的人(Paul C. Betts)维护的.
我对它很陌生,我可能会对StackOverflow充满疑问,因为我拥有巨大的力量,我认为它值得学习和掌握.
让我们进入细节:
我一直使用View-First.我是Cinch Framework的资深用户(http://cinch.codeplex.com/)
它使用MEF将ViewModel注入每个View.您只需使用[ViewModel("SampleView")]装饰ViewModel并向View添加一个附加属性(ViewModelLocator.ViewModel ="SampleView"),每当View加载时,相应的ViewModel将被实例化并注入其中DataContext与您选择的生命周期.
这种机制虽然有效,但也有一些不便之处.最糟糕的是:它使用了一个定位器.
正如Mark Seemann在他的书中所说,ServiceLocator是一种应该避免的反模式.
我有一个继承ReactiveObject自reactiveui.net的视图模型,类似于
public sealed class TestViewModel : ReactiveObject
{
public sealed class NestedViewModel
{
private string _property;
public string VMProperty
{
get { return _property; }
set { this.RaiseAndSetIfChanged(ref _property, value); }
}
private string _suffix;
public string Suffic
{
get { return _suffix; }
set { this.RaiseAndSetIfChanged(ref _suffix, value); }
}
}
private NestedViewModel _nested = new NestedViewModel();
public Nested
{
get { return _nested; }¨
set { this.RaiseAndSetIfChanged(ref _nested, value); }
}
#if DEBUG
public …Run Code Online (Sandbox Code Playgroud) 假设我有以下视图模型:
public class AddressViewModel : ReactiveObject
{
private string line;
public string Line
{
get { return this.line; }
set { this.RaiseAndSetIfChanged(x => x.Line, ref this.line, value); }
}
}
public class EmployeeViewModel : ReactiveObject
{
private AddressViewModel address;
public AddressViewModel Address
{
get { return this.address; }
set { this.RaiseAndSetIfChanged(x => x.Address, ref this.address, value); }
}
}
Run Code Online (Sandbox Code Playgroud)
现在假设EmployeeViewModel我希望公开一个具有最新值的属性Address.Line:
public EmployeeViewModel()
{
this.changes = this.ObservableForProperty(x => x.Address)
.Select(x => x.Value.Line)
.ToProperty(this, x => x.Changes);
} …Run Code Online (Sandbox Code Playgroud) 我们目前正在使用ReactiveUI来帮助构建一个相当大的基于WPF的Windows应用程序.一切进展顺利,直到我们发现我们的应用程序消耗了大量内存...基本上我们的所有视图,视图模型和模型都没有被垃圾收集.
基于来自内存分析器的信息,例如Jet Brains dotMemory,ReactiveUI似乎是主要的罪魁祸首.特别是我们在视图中配置的ReactiveUI绑定,即使我们使用最佳实践并确保在取消激活视图时处置所有绑定.
以下是我们正在创建的其中一个视图的示例.任何关于我们可能出错的想法都将不胜感激.
public partial class RunbookInputsView : IViewFor<RunbookInputsViewModel>
{
public static readonly DependencyProperty ViewModelProperty = DependencyProperty.Register(
"ViewModel", typeof(RunbookInputsViewModel), typeof(RunbookInputsView));
public RunbookInputsView()
{
InitializeComponent();
this.WhenActivated(d =>
{
d(this.OneWayBind(ViewModel, vm => vm.AddInput, v => v.AddInput.Command));
d(this.OneWayBind(ViewModel, vm => vm.Inputs, v => v.Inputs.ItemsSource));
});
}
object IViewFor.ViewModel
{
get { return ViewModel; }
set { ViewModel = (RunbookInputsViewModel)value; }
}
public RunbookInputsViewModel ViewModel
{
get { return (RunbookInputsViewModel) GetValue(ViewModelProperty); }
set { SetValue(ViewModelProperty, value); }
}
}
Run Code Online (Sandbox Code Playgroud) 我目前正在尝试使用NUnit和Moq设置Unit来对我们的ReactiveUI ViewModels进行单元测试.但是我无法让它发挥作用.我无法将ReactiveUI添加到NUnit测试库(无法解析依赖关系'Rx-Xaml(≥2.2.5)'),我无法将Moq添加到PCL项目中.
是否可以使用NUnit和Moq对ReactiveUI ViewModels进行单元测试?
顺便说一句:我在Mac OSX 10.10.5上使用Xamarin Studio,但代码在Windows 10上正常运行:(
在OSX上我得到一个Unix传输错误,但在Windows上测试确实有效.
我有一个针对.Net 4.5.2的多项目Visual Studio解决方案.在其中一个项目(WPF应用程序)中,我使用nuget添加System.Reactive版本3.0.1000.0包,然后添加ReactiveUI 7.0.0.0包.
在WPF应用程序使用的另一个项目库中,我只添加了System.Reactive版本3.0.1000.0包.
ReactiveUI包似乎依赖于一组旧的反应包(RX-Core2.2.5等).我可以告诉你,因为WPF应用程序项目文件中的HintPaths指向诸如packages\Rx-Core.2.2.5\lib \net45\System.Reactive.Core.dll之类的位置
当我构建并运行应用程序时,我得到一个FileLoadException,因为至少有一个项目试图使用错误的dll版本.以下是典型的....
System.IO.FileLoadException occurred
HResult=0x80131040
Message=Could not load file or assembly 'System.Reactive.Linq, Version=3.0.1000.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
Run Code Online (Sandbox Code Playgroud)
我可以通过将解决方案中的所有System.Reactive软件包降级到2.2.5来解决这个问题,但这似乎是一个非常旧的版本(2014).
为什么ReactiveUI会依赖System.Reactive的v2.2.5?有没有办法改变这种行为,以便我可以在整个解决方案中使用最新版本的System.Reactive?
我正在编写一个程序,它是其他较小程序的容器.它通过Assembly.Load加载它的模块,找到实现IModule的类型并创建它们的实例.
在WPF MainWindow中,我有一个RoutedViewHost,它将显示所有内容.
在我的AppBoostrapper中,我有以下内容:
private ReactiveList<IModule> LoadModules(IMutableDependencyResolver resolver)
{
var modules = ModuleLoader.Load(ModulesDirectory);
// var modules = new IModule[] { new SampleModuleClass(), }; // this works perftectly!
foreach (var module in modules)
{
try
{
module.RegisterDependencies(this, resolver);
}
catch (Exception e)
{
Log.Error(e, "Could not register dependecies for module " + module.Name);
}
}
Log.Debug("Modules loaded: " + string.Join(", ", modules.Select(x => x.Name)));
return new ReactiveList<IModule>(modules);
}
Run Code Online (Sandbox Code Playgroud)
然后,在我的示例模块中:
public void RegisterDependencies(IMainScreen screen, IMutableDependencyResolver resolver)
{
_screen = screen;
_resolver = …Run Code Online (Sandbox Code Playgroud) 我无法ViewModelViewHost在Visual Studio的设计时间工作.这是设计还是我设置错了?
在我看来,我有:
Locator.CurrentMutable.InitializeSplat();
Locator.CurrentMutable.InitializeReactiveUI();
Locator.CurrentMutable.Register(() => new SessionView(), typeof(IViewFor<SessionViewModel>));
Run Code Online (Sandbox Code Playgroud)
在我看来的XAML我有:
<d:DesignProperties.DataContext>
<local:MainWindowViewModel>
<local:MainWindowViewModel.ChildViewModel>
<local:SessionViewModel/>
</local:MainWindowViewModel.ChildViewModel>
</local:MainWindowViewModel>
</d:DesignProperties.DataContext>
<reactiveUi:ViewModelViewHost ViewModel="{Binding ChildViewModel}"/>
Run Code Online (Sandbox Code Playgroud)
SessionView是一个IViewFor<SessionViewModel>.
有评论这里在ViewModelViewHost表明在设计模式,它会试图创建一个视图之前返回构造函数.但是,InUnitTestRunner如果InDesignMode为此目的存在单独的属性,则应该返回true 似乎很奇怪.
// NB: InUnitTestRunner also returns true in Design Mode
if (ModeDetector.InUnitTestRunner()) {
ViewContractObservable = Observable.Never<string>();
return;
}
Run Code Online (Sandbox Code Playgroud) reactiveui ×10
c# ×7
wpf ×4
.net ×2
mvvm ×2
memory-leaks ×1
moq ×1
nuget ×1
nunit ×1
reactive ×1
unit-testing ×1
xamarin ×1
xaml ×1