基于日期 Xamarin 表单过滤 ObservableCollection

Posted

技术标签:

【中文标题】基于日期 Xamarin 表单过滤 ObservableCollection【英文标题】:Filter ObservableCollection based on date Xamarin Forms 【发布时间】:2017-09-18 12:30:29 【问题描述】:

第一次发帖,如有错误,请见谅。

我在根据给定日期过滤可观察集合时遇到问题。该应用程序将有一个日历,用户可以在其中单击一个日期,下面将显示该日期的约会。

有两个类,一个是从 Azure 获取数据的 dataManager,另一个是约会页面本身。

这里是约会页面类:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using XamForms.Controls;

namespace TodoAzure

    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class AppointmentPage : ContentPage
    
        TodoItemManager manager;
        CalendarVM vm = new CalendarVM();
        public AppointmentPage()
        
            InitializeComponent();
            manager = TodoItemManager.DefaultManager;
            calendar.DateClicked += (sender, e) =>
            
                System.Diagnostics.Debug.WriteLine(calendar.SelectedDates);
            ;
            calendar.SetBinding(Calendar.DateCommandProperty, nameof(vm.DateChosen));
            calendar.SetBinding(Calendar.SelectedDateProperty, nameof(vm.DateSelected));
            calendar.BindingContext = vm;
        
        protected override async void OnAppearing()
        
            base.OnAppearing();
            // Set syncItems to true in order to synchronize the data on startup when running in offline mode
            await RefreshItems(true, syncItems: false);
        
        //PULL TO REFRESH
        public async void OnRefresh(object sender, EventArgs e)
        
            var list = (ListView)sender;
            Exception error = null;
            try
            
                await RefreshItems(false, true);
            
            catch (Exception ex)
            
                error = ex;
            
            finally
            
                list.EndRefresh();
            
            if (error != null)
            
                await DisplayAlert("Refresh Error", "Couldn't refresh data (" + error.Message + ")", "OK");
            
        
        public async void OnSyncItems(object sender, EventArgs e)
        
            await RefreshItems(true, true);
        
        private async Task RefreshItems(bool showActivityIndicator, bool syncItems)
        
            using (var scope = new ActivityIndicatorScope(syncIndicator, showActivityIndicator))
        
            appointmentPage.ItemsSource = await manager.GetAppointmentItemsAsync(syncItems);      
        
    
    private class ActivityIndicatorScope : IDisposable
    
        private bool showIndicator;
        private ActivityIndicator indicator;
        private Task indicatorDelay;
        public ActivityIndicatorScope(ActivityIndicator indicator, bool showIndicator)
        
            this.indicator = indicator;
            this.showIndicator = showIndicator;
            if (showIndicator)
            
                indicatorDelay = Task.Delay(2000);
                SetIndicatorActivity(true);
            
            else
            
                indicatorDelay = Task.FromResult(0);
            
        
        private void SetIndicatorActivity(bool isActive)
        
            this.indicator.IsVisible = isActive;
            this.indicator.IsRunning = isActive;
        
        public void Dispose()
        
            if (showIndicator)
            
                indicatorDelay.ContinueWith(t => SetIndicatorActivity(false), TaskScheduler.FromCurrentSynchronizationContext());
            
        
    

这里是数据管理器类:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.WindowsAzure.MobileServices;
using Microsoft.WindowsAzure.MobileServices.Sync; 
#if OFFLINE_SYNC_ENABLED
using Microsoft.WindowsAzure.MobileServices.SQLiteStore;
using Microsoft.WindowsAzure.MobileServices.Sync;
#endif

namespace TodoAzure

    public partial class TodoItemManager
    
        static TodoItemManager defaultInstance = new TodoItemManager ();
        MobileServiceClient client;
        IMobileServiceTable<TodoItem> todoTable;
        IMobileServiceTable<AppointmentItem> appointmentTable;
        private TodoItemManager ()
        
            this.client = new MobileServiceClient (
                Constants.ApplicationURL);
            this.todoTable = client.GetTable<TodoItem> ();
            this.appointmentTable = client.GetTable<AppointmentItem>();  
         
        public static TodoItemManager DefaultManager 
        
            get  return defaultInstance; 
            private set  defaultInstance = value; 
           
        public MobileServiceClient CurrentClient 
        
            get  return client; 
          
        public bool IsOfflineEnabled 
        
            get  return appointmentTable is Microsoft.WindowsAzure.MobileServices.Sync.IMobileServiceSyncTable<AppointmentItem>;        
       
    // INSERT AND UPDATE METHODS
    public async Task SaveTaskAsync (TodoItem item)
    
        if (item.Id == null) 
            await todoTable.InsertAsync (item);
        else 
            await todoTable.UpdateAsync (item);
    
    public async Task SaveTaskAsync(AppointmentItem appointment)
    
        if (appointment.Id == null)
            await appointmentTable.InsertAsync(appointment);
        else
            await appointmentTable.UpdateAsync(appointment);
    
    public async Task<ObservableCollection<AppointmentItem>> GetAppointmentItemsAsync(bool syncItems = false)
    
        try
        
            IEnumerable<AppointmentItem> items = await appointmentTable
                    .ToEnumerableAsync();
            return new ObservableCollection<AppointmentItem>(items);
        
        catch (MobileServiceInvalidOperationException msioe)
        
            Debug.WriteLine(@"Invalid sync operation: 0", msioe.Message);
        
        catch (Exception e)
        
            Debug.WriteLine(@"Sync error: 0", e.Message);
        
        return null;
    

任何帮助将不胜感激。

【问题讨论】:

“遇到麻烦” - 你能更具体一点吗?您是否收到错误或异常?它的行为是奇怪的,还是崩溃的?我在您的代码中没有看到任何甚至尝试进行日期过滤的逻辑? 我不确定如何使用约会页面中vm.SelectedDates 中给出的日期过滤 ObservableCollection。我尝试了其他 Stack Overflow Questions 中给出的几种方法,但都没有成功。 【参考方案1】:

要按日期过滤 IEnumerable,试试这个

// items is ObservableCollection<AppointmentItem>
var filtered = items.Where(x => x.Date == SelectedDate);

【讨论】:

它不起作用):过滤是否必须在 AppointmentPage 类中进行,因为这是用户定义 SelectedDate 的地方? 查看我的编辑 - 在我的示例中,我使用了类名而不是实例名。如果它仍然不起作用,请更具体 - 您是否在调试器中验证正在返回过滤的数据列表?至于您将过滤器表达式放在哪里,这取决于您。 我现在看到此错误“错误 CS1061 'Task>' 不包含 'Where' 的定义并且没有扩展方法 'Where' 接受类型为 'Task 的第一个参数>' 可以找到(您是否缺少 using 指令或程序集引用?)”。缓慢但肯定会到达那里。 您需要包含“System.LINQ;”在您的 using 语句中

以上是关于基于日期 Xamarin 表单过滤 ObservableCollection的主要内容,如果未能解决你的问题,请参考以下文章

按日期字段过滤子表单

xamarin 表单中的 datepicker 和 timepicker 多次触发 Focus 和 Unfocus 事件

在基于 Xamarin 表单的应用程序中将数据从 android 服务传递到 ContentPage

使用两个未绑定的文本框按日期范围过滤表单记录

如何按日期过滤并按代码进行表单查询?

Xamarin 表单 - GetBindingExpression