1

我有一個對象的列表,類型Emblem,我在LongListMultiSelector中顯示。我只想展示那些還沒有實現的。我可以選擇一個或多個項目並將它們更改爲IsAchieved = true,但問題是它們不會立即消失,UI不會自動更新。(真的)ObservableCollection <T>不更新UI

我認爲這不會是一個問題,因爲我使用了ObservableCollection<T>。然後我發現如果一個項目的屬性發生變化,那麼這個集合就不會被通知。結果實現了INotifyPropertyChanged接口,但這也不起作用。

在這裏,所以我發現以下問題(及以上)共享此問題:

我也嘗試過推行的用法TrulyObservableCollection<T>但也沒有結果。下面是我有

XAML控制:

<toolkit:LongListMultiSelector Name="EmblemsList" 
           ItemsSource="{Binding Emblems}" 
           Background="Transparent" 
           LayoutMode="List" 
           ItemTemplate="{StaticResource ItemTemplate}" /> 

項目通過EmblemsViewModel約束:

public class EmblemsViewModel 
{ 
    public EmblemsViewModel() 
    { 
     Emblems = new TrulyObservableCollection<Emblem>(); 
    } 

    public TrulyObservableCollection<Emblem> Emblems { get; set; } 
} 

//Usage on the page 
DataContext = new EmblemsViewModel { Emblems = DB.GetEmblems() } 

Emblem類如下:

public class Emblem : Achievement 
{ 
    public int Level { get; set; } 
} 

public abstract class Achievement : INotifyPropertyChanged 
{ 
    private bool _isAchieved; 

    public string Description { get; set; } 

    public bool IsAchieved 
    { 
     get { return _isAchieved; } 
     set 
     { 
      if (_isAchieved != value) 
      { 
       _isAchieved = value; 
       NotifyPropertyChanged("IsAchieved"); 
      } 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
    private void NotifyPropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 

} 

我在想什麼/做錯了,阻止這個工作?

更新:

我申請一個CollectionViewSource應用過濾,但現在沒有項目中。

//Reference to the CollectionViewSource 
_viewSource = (CollectionViewSource)Resources["EmblemsViewSource"]; 

//3 options in the ListBox: all, achieved & unachieved 
private void FilterListBoxSelectionChanged(object sender, SelectionChangedEventArgs e) 
{ 
    var selectedItem = ((ListBoxItem)FilterListBox.SelectedItem).Content.ToString(); 

    switch (selectedItem) 
    { 
     case "achieved": _filter = Filter.Achieved; _viewSource.Filter += new FilterEventHandler(CollectionViewSource_Filter); break; 
     case "unachieved": _filter = Filter.Unachieved; _viewSource.Filter += new FilterEventHandler(CollectionViewSource_Filter); break; 
     default: _filter = Filter.All; _viewSource.Filter -= new FilterEventHandler(CollectionViewSource_Filter); break; 
    } 
} 

private void CollectionViewSource_Filter(object sender, FilterEventArgs e) 
{ 
    var item = e.Item as Emblem; 

    switch (_filter) 
    { 
     case Filter.Achieved: e.Accepted = item.IsAchieved; break; 
     case Filter.Unachieved: e.Accepted = !item.IsAchieved; break; 
     case Filter.All: e.Accepted = true; break; 
    } 
} 

XAML:

<CollectionViewSource x:Key="EmblemsViewSource" Source="{Binding Emblems}" /> 

<toolkit:LongListMultiSelector Name="EmblemsList" 
           ItemsSource="{Binding Source={StaticResource EmblemsViewSource}}" 
           Background="Transparent" 
           LayoutMode="List" 
           ItemTemplate="{StaticResource ItemTemplate}" /> 
+1

您在哪裏篩選出XAML中IsAchieved = true的元素? – 2014-10-20 09:25:59

+0

是那個實際的初始化代碼? – thumbmunkeys 2014-10-20 09:32:42

+0

@OndrejSvejdar我沒有實現這一點。現在我有但沒有項目顯示。查看更新後的問題以獲取更多信息。 – Abbas 2014-10-20 10:47:48

回答

1

一種解決方案可能是您創建一個從ObservableCollection衍生一個新的集合,並添加一個新的屬性如。 FilteredItems

主窗口

public partial class MainWindow : Window 
{ 
    FilterableObservableCollection items; 

    public MainWindow() 
    { 

     items = new FilterableObservableCollection() 
     { 
      new ListViewItem() { Name = "Hallo", IsArchived = false }, 
      new ListViewItem() { Name = "world", IsArchived = true }, 
      new ListViewItem() { Name = "!!!", IsArchived = false } 
     }; 

     InitializeComponent(); 
    } 

    public FilterableObservableCollection MyItems 
    { 
     get { return items; } 
    } 

    private void CheckBox_Checked(object sender, RoutedEventArgs e) 
    { 
     items.NotArchivedOnlyFilterEnabled = (sender as CheckBox).IsChecked.Value; 
    } 

    private void CheckBox_Unchecked(object sender, RoutedEventArgs e) 
    { 
     items.NotArchivedOnlyFilterEnabled = (sender as CheckBox).IsChecked.Value; 
    } 

    private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     items.Add(new ListViewItem() { Name = "Item" + (items.Count + 1), IsArchived = items.Count % 2 == 0 }); 
    } 
} 

定製觀察集合

public class FilterableObservableCollection : ObservableCollection<ListViewItem> 
{ 
    private bool notArchivedOnlyFilterEnabled; 

    public IEnumerable<ListViewItem> FilteredItems 
    { 
     get 
     { 
      if (notArchivedOnlyFilterEnabled) 
      { 
       return this.Where(x => x.IsArchived == false); 

      } 
      else 
      { 
       return this; 
      } 
     } 
    } 

    public bool NotArchivedOnlyFilterEnabled 
    { 
     get { return notArchivedOnlyFilterEnabled; } 
     set 
     { 
      notArchivedOnlyFilterEnabled = value; 
      OnPropertyChanged(new PropertyChangedEventArgs("FilteredItems")); 
     } 
    } 
} 

數據項

public class ListViewItem 
{ 
    public string Name { get; set; } 

    public bool IsArchived { get; set; } 
} 

XAML

<Window x:Class="ObservableCollectionDemo1.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" Height="350" Width="525" 
     DataContext="{Binding RelativeSource={RelativeSource Self}}" 
     xmlns:c="clr-namespace:ObservableCollectionDemo1"> 
    <Grid> 
     <ListView HorizontalAlignment="Left" Height="142" Margin="81,47,0,0" VerticalAlignment="Top" Width="302" x:Name="listView" DataContext="{Binding MyItems}" ItemsSource="{Binding FilteredItems}"> 
      <ListView.View> 
       <GridView> 
        <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}" Width="100"/> 
        <GridViewColumn Header="Is Archived" DisplayMemberBinding="{Binding IsArchived}" Width="100"/> 
       </GridView> 
      </ListView.View> 
     </ListView> 
     <CheckBox Content="Is Not Archived" HorizontalAlignment="Left" Margin="278,194,0,0" VerticalAlignment="Top" Checked="CheckBox_Checked" Unchecked="CheckBox_Unchecked"/> 
     <Button Content="New Item" HorizontalAlignment="Left" Margin="278,214,0,0" VerticalAlignment="Top" Width="105" Click="Button_Click"/> 

    </Grid> 
</Window> 
1

你只需要建立一個收集過濾一次,而不是每一次過濾器選項更改。單個電話

_viewSource.Filter += new FilterEventHandler(CollectionViewSource_Filter); 

應該是你所需要的,然後在你的列表框選擇改變你可以調用_viewSource。 Refresh()強制過濾器謂詞重新評估列表項目。

另一種選擇可能是具有表示徽可見性屬性直接綁定到使用轉換器EmblemIsAchieved屬性XAML數據模板:

​​

BoolVisibilityConverterValueConverter

您必須嘗試一下,看看它是否適合您的場景 - 運行大量值轉換器可能會損害大型數據集,但它具有簡單的優勢!

相關問題