0

ListView绑定了一个数据实例

ObservalbeCollection<ActivityItem> ActivityItems

            <ListView
                x:Name="ActivityItemsList"
                ItemsSource="{Binding ActivityItems}"
                ItemTemplate="{StaticResource Herke80ItemTemplate}"
                Header="{Binding DateFilterListBox.SelectedItem}" />

当我运行过滤器时,我想在 ListView 中选择绑定到 ActivityItem 的 ListViewItem,并根据所选过滤器更改其可见性。

我通过保留另一个 ObservableCollection 实例来做到这一点,这意味着数据实例被复制了。然后我相应地删除或添加了项目。这占用了大量的加载时间。所以我想我会尝试保持一个绑定,并禁用或启用 UI 元素。

        foreach (ActivityItem activityItem in ActivityItemsList.Items)
        {
            if (activityItem == null) continue;

            var index = ActivityItemsList.Items.IndexOf(activityItem);

            (ActivityItemsList.Items[index] as ListViewItem).Visibility = Visibility.Collapsed;

            int startComparer = DateTime.Compare(activityItem.Start, selectedStartDate);
            int endComparer = DateTime.Compare(selectedEndDate, activityItem.End);

            if (OverdueToggleSwitch.IsOn)
            {
                (ActivityItemsList.Items[index] as ListViewItem).Visibility = Visibility.Visible;
            }
            else
            {
                if (startComparer >= 0 && endComparer >= 0)
                {
                    (ActivityItemsList.Items[index] as ListViewItem).Visibility = Visibility.Visible;
                }
            }
        }

ex 是 NullReferenceException,因为 ListViewItem 实际上不是 ListViewItem 而是 ActivityItem。

这样做的替代方法或正确方法是什么?

4

1 回答 1

0

我认为你把它复杂化了。如果您使用Snoop,您可以看到,当您通过 ItemSource 将 ListView 绑定到集合时,它最终会填充 ListViewItems 的集合,其中每个 ListViewItem 有两个东西。

  1. 设置为数据的 DataContext(例如 ActivityItem)
  2. 填充了 DataTemplate 中定义的控件的 ContentPresenter

这意味着理论上您可以浏览这两个集合

from x in listView.Items select x as ListViewItem

或者

from x in listView.Items select x.DataContext as ActivityItem

但是,如果您只是想要一个过滤列表,那么我可以建议更改您的绑定,

 <ListView
            x:Name="ActivityItemsList"
            ItemsSource="{Binding FilteredItems}"

public class MyViewModel :INotifyPropertyChanged    
{
   public IEnumerable<ActivityItem> AllItems {get;set;} //needs to NotifyPropertyChanged(FilteredItems)
   public Func<ActivityItem, bool> Filter { get;set;} //needs to NotifyPropertyChanged(FilteredItems)
   public IEnumerable<ActivityItem> FilteredItems { get { return from x in AllItems where Filter(x) select x; }}
}

如果您仍在为性能问题苦苦挣扎,请快速阅读 Bea Costa 关于 TreeView 性能的系列文章第一部分第二部分第三部分。它可能会帮助您让 WPF 为您完成所有艰苦的工作。

于 2013-06-06T14:02:58.833 回答