我有一个Windows应用商店应用(或Metro风格/ WinRT / Windows运行时),它有一个CollectionViewSource,它绑定到代码隐藏文件中的ListView。没有排序和/或分组所有工作正常,UI得到更新。但是只要我对CollectionViewSource的Source进行排序或分组,UI就会停止更新。在MainPage中设置绑定:
public MainPage()
{
InitializeComponent();
ViewModel = new MainPageVm();
DataContext = ViewModel;
Binding myBinding = new Binding();
myBinding.Mode = BindingMode.TwoWay;
myBinding.Source = ViewModel.UpcomingAppointments;
UpcomingListView.SetBinding(ListView.ItemsSourceProperty, myBinding);
//Timer to update the UI periodically
var Timer = new DispatcherTimer {Interval = TimeSpan.FromSeconds(60)};
Timer.Tick += (o, e) => ViewModel.LoadData();
Timer.Start();
}
viewmodel的相关部分:
public class MainPageVm : INotifyPropertyChanged
{
public MainPageVm()
{
Appointments = new ObservableCollection<Appointment>();
Appointments.CollectionChanged += delegate { NotifyPropertyChanged("UpcomingAppointments"); };
}
public ObservableCollection<Appointment> Appointments
{
get { return appointments; }
set
{
if (appointments != value)
{
appointments = value;
NotifyPropertyChanged();
NotifyPropertyChanged("UpcomingAppointments");
}
}
}
public CollectionViewSource UpcomingAppointments
{
get
{
return new CollectionViewSource
{
//removing Where an Groupby and set IsSourceGrouped = false get the UI updated again
Source = Appointments
.Where(a => a.Start > DateTime.UtcNow)
.GroupBy(x => x.Day),
IsSourceGrouped = true
};
}
}
public async Task LoadData()
{
var Repo = new WebserviceRepository();
await Repo.GetAppointments();
Appointments.Clear;
foreach (Appointment Appointment in Repo.Appointments)
{
Appointments.Add(Appointment);
}
NotifyPropertyChanged("UpcomingAppointments");
NotifyPropertyChanged("Appointments");
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
相关的XAML部分:
<ListView Name="UpcomingListView" ItemTemplate="{StaticResource AppointmentListTemplate}">
<ListView.GroupStyle>
<GroupStyle HidesIfEmpty="False">
<GroupStyle.HeaderTemplate>
<DataTemplate>
<Grid>
<TextBlock Text="{Binding Key}" />
</Grid>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ListView.GroupStyle>
最后是约会课:
public class Appointment
{
public Guid AppointmentId { get; set; }
public string Description { get; set; }
public DateTime Start { get; set; }
public DateTime End { get; set; }
public string Day
{
get
{
if (this.Start.Date == DateTime.Now.Date){return "Today";}
if (this.Start.Date == (DateTime.Now.AddDays(1).Date)) { return "Tomorrow";}
If (this.Start.Date == (DateTime.Now.AddDays(2).Date)){ return "Day After Tomorrow";}
return string.Empty;
}
}
}
因此,删除.Where和.Sort并将IsSourceGrouped设置为false会再次更新UI,但当然是未排序的,而不是所需的分组。
当我在ViewModel的构造函数中设置数据时,该数据会显示(分组与否)但不会更新
正如您所看到的,每当运行LoadData时我都会调用NotifyPropertyChanged,以确保它被调用。在Appointments OberservableCollection-s Collection更改后,我也运行NotifyPropertyChanged。
显然,Where过滤和GroupBy分组需要一些我不知道的其他调整。我在SO上看到很多关于分组的问题,但似乎它们是关于WPF(并且这是不同的)或者在XAML中设置所有绑定和静态资源(我不想这样做)。
所以我的基本问题是:如何使用C#代码隐藏文件对ListView中的UpcomingAppointments进行分组和排序?