【问题标题】:ListView binding cast items to ListViewItemListView 将强制转换项目绑定到 ListViewItem
【发布时间】:2013-06-06 22:02:58
【问题描述】:

我有一个绑定到数据实例的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。

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

【问题讨论】:

  • 您可以使用ICollectionView。在 WPF 4.5 中,实时整形功能变得更加强大。
  • 您好,这是针对 Windows 8 的,CollectionViewSource 似乎没有 GetDefaultView 方法。
  • 我不是建议你使用默认的集合视图,而是创建你自己的实例。查看ICollectionView的实现。

标签: c# wpf windows xaml data-binding


【解决方案1】:

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

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

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

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 性能系列part onepart twopart three。它可能会帮助您让 WPF 为您完成所有艰苦的工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-12
    • 1970-01-01
    • 2013-01-01
    • 1970-01-01
    相关资源
    最近更新 更多