ReactiveUI"引人注目的例子"使用Caliburn.Micro.ReactiveUI进行搜索

时间:2016-01-17 21:14:35

标签: linq linq-to-entities reactiveui caliburn.micro.reactiveui

我有一个使用Caliburn.Micro构建的现有Wpf应用程序,我想开始集成ReactiveUI。首先,我从Caliburn.Micro切换到Caliburn.Micro.ReactiveUI库。

我有一个ListBox,它使用Caliburn Micro的约定绑定到BindableCollection。我使用CM来查找MyViewModel的视图,并使用EntityFramework执行搜索来填充BindableCollection。

我试图实现异步"引人注目的例子"显示但是每当执行搜索时,ReactiveUI.dll都会抛出并取消处理InvalidCastException。我无法看到任何详细信息,因为我没有ReactiveUI.pdb符号文件。我将我的BindableCollection属性包装在ObservableAsPropertyHelper中,以便当用户执行搜索时,ReactiveUI将更新BindableCollection,以便Caliburn.Micro可以像往常那样做。

有谁知道导致无效演员表异常的原因是什么?我对CM有一定的经验,但是Rx和RxUI的新手。所以,我可能会完全以错误的方式解决这个问题。

以下是相关代码:

public class MainViewModel: ReactiveScreen
{
        private ObservableAsPropertyHelper<BindableCollection<MyViewModel>> _myViewModels;
        public BindableCollection<MyViewModel> MyViewModels
        {
            get { return _myViewModels.Value; }
        }

        [ImportingConstructor]
        public MainViewModel(IEventAggregator eventAggregator)
        {

            _myEntities = new myEntities();
            var searchService = new SearchService(_myEntities);
            Items.CollectionChanged += delegate
            {
                NotifyOfPropertyChange(() => Status);
            };
            var searchTerms = this
                .ObservableForProperty(x => x.SearchTerm)
                .Value()
                .Throttle(TimeSpan.FromSeconds(.5));
            var searchResults = searchTerms.SelectMany(searchTerm => searchService.SearchAsync(searchTerm));
            var latestMatches = searchTerms
               .CombineLatest(searchResults,
                   (searchTerm, searchResult) =>
                       searchResult.SearchTerm != searchTerm
                           ? null
                           : searchResult.Matches)
               .Where(matches => matches != null);
            _myViewModels= latestMatches.ToProperty(this, x => x.MyViewModels);

        }
}

SearchService如下所示:

public class SearchService
    {
        private MyEntities _myEntities;
        public SearchService(MyEntities myEntities)
        {
            _myEntities= myEntities;
        }
        public async Task<SearchResult> SearchAsync(string searchTerm)
        {
            var query = await (from m in _myEntities.Employees select m).ToListAsync();
            if (!String.IsNullOrEmpty(searchTerm))
            {
                searchTerm = searchTerm.Trim();
                query = (List<Employee>) query.Where(
                    x => x.LastName.Contains(searchTerm) || x.FirstName.Contains(searchTerm))
                    .Select(x => x);
            }
            return new SearchResult
            {
                SearchTerm = searchTerm,
                Matches = new BindableCollection<MyViewModel>(query.Select(x => new MyViewModel{ Employee = x }))
            };

        }
    }

信息搜索结果:

public class SearchResult
    {
        public string SearchTerm { get; set; }
        public BindableCollection<MyViewModel> Matches { get; set; }
    }

谢谢,

肖恩

编辑:

我在不同位置设置断点后得到了异常的详细信息。

消息:

{&#34;在一个会破坏绑定或命令的对象(通常是ObservableAsPropertyHelper)上发生OnError。要防止这种情况,请订阅对象的ThrownExceptions属性&#34;}

内部例外:

{&#34;无法转换类型为WhereSelectListIterator 2[HR.DataContext.Models.Employee,HR.DataContext.Models.Employee]' to type System.Collections.Generic.List的对象1 [HR.DataContext.Models.Employee]&#39;。&#34;}

堆栈跟踪:

at ReactiveUI.RxApp.<>c__DisplayClass5.<.cctor>b__2()
   at System.Reactive.Concurrency.Scheduler.Invoke(IScheduler scheduler, Action action)
   at System.Reactive.Concurrency.DispatcherScheduler.<>c__DisplayClass1`1.<Schedule>b__0()
   at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)

1 个答案:

答案 0 :(得分:1)

你的问题在线:

query = (List<Employee>)
    query
        .Where(x => x.LastName.Contains(searchTerm)
            || x.FirstName.Contains(searchTerm))
        .Select(x => x);

查询类型似乎为List<Employee>,但query.Where(...).Select(...)返回的类型不是。

您最后需要添加.ToList()。它应该是这样的:

query = //(List<Employee>) no need to cast now
    query
        .Where(x => x.LastName.Contains(searchTerm)
            || x.FirstName.Contains(searchTerm))
        .ToList();

我删除了.Select(x => x),因为它没有做任何事情。