簡體   English   中英

綁定到ObservableCollection以顯示第一個X數量的項目c#WPF

[英]Binding to an ObservableCollection to show the first X number of items c# WPF

背景說明

好的,所以我現在將ContextMenu ItemsSource綁定到ObservableCollection ,比如TypeA

以下代碼位於單例類DataStore中

private ObservableCollection<TypeA> TypeACollection = new ObservableCollection<TypeA>();

public ObservableCollection<TypeA> GetTypeACollection
{
    get { return TypeACollection; }
}
public ObservableCollection<TypeA> GetFirstFiveTypeACollection
{
    get 
    {
        return TypeACollection.Take(5);
    }
}

現在我已經使用以下XAML代碼成功地將ItemsControl綁定到GetTypeACollection

以下代碼位於MainWindow.xaml中

<ItemsControl x:Name="TypeAList" ItemsSource="{Binding GetTypeACollection, Source={StaticResource DataStore}, UpdateSourceTrigger=PropertyChanged}" >
<ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
        <VirtualizingStackPanel />
    </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <User_Controls:TypeAUserControl Type="{Binding }"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

這按預期工作,顯示TypeAUserControl ,使用TypeA的數據按預期正確格式化

現在,當我嘗試通過將ItemsSource綁定到GetFirstFiveTypeACollectionContextMenu MenuItem上重復此操作時,我最初會看到預期的結果,但是在刪除TypeA對象時,MainWindow ItemsControl會更新,而ContextMenu則不會。

我相信這是因為綁定本身位於ContextMenu和' ObservableCollection<TypeA> (如GetFirstFiveTypeAColletion )。

我也通過使用IValueConverter嘗試了這一點

以下代碼在ValueConverters類中

public class ObservableCollectionTypeAResizeConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        ObservableCollection<TypeA> TypeACollection = value as ObservableCollection<TypeA>;

        return TypeACollection.Take(System.Convert.ToInt32(parameter));
    }
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return null;
    }
}

我嘗試過的XAML代碼。

使用IValueConverter

<MenuItem Header="First 5 Type A" Name="MI_FirstFiveTypeA" 
    ItemsSource="{Binding DATA_STORE.GetTypeACollection, ConverterParameter=5,
            Converter={StaticResource ObservableCollectionTypeAResizeConverter}, 
            Source={StaticResource DataStore}}" 
/>

使用GetFirstFiveTypeACollection

<MenuItem Header="First 5 Type A" Name="MI_FirstFiveTypeA" 
    ItemsSource="{Binding DATA_STORE.RecentTimers, Source={StaticResource DataStore}, 
            UpdateSourceTrigger=PropertyChanged}"
/>

我不知道下一步該怎么做,或者我應該怎么做,任何幫助都將不勝感激!

編輯

好的,所以我改變了以下內容

DataStore.cs

private ObservableCollection<TimerType> TimerTypes = new ObservableCollection<TimerType>();

public ObservableCollection<TimerType> getTimerTypes
{
    get 
    { 
        return new ObservableCollection<TimerType>(TimerTypes.OrderByDescending(t => t.LastUsed)); 
    }
}
public ObservableCollection<TimerType> RecentTimers
{
    get 
    { 
        return new ObservableCollection<TimerType>(TimerTypes.OrderByDescending(t => t.LastUsed).Take(5)); 
    }
}

public event PropertyChangedEventHandler PropertyChanged;

// Create the OnPropertyChanged method to raise the event
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
    if (PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}
//THIS IS IN THE ADD METHOD
TimerTypes.Add(timer);
NotifyPropertyChanged("getTimerTypes");
NotifyPropertyChanged("RecentTimers");
NotifyPropertyChanged("TimerTypes");

//THIS IS IN THE REMOVE METHOD
TimerTypes.Remove(Timer);
NotifyPropertyChanged("getTimerTypes");
NotifyPropertyChanged("RecentTimers");
NotifyPropertyChanged("TimerTypes");

MainWindow.xaml

<ItemsControl x:Name="TimersList" ItemsSource="{Binding Path=getTimerTypes, UpdateSourceTrigger=PropertyChanged}" >

MainWindow.xaml.cs

//Lists are populated in DataStore.cs before this.
DataContext = DataStore.DATA_STORE;
InitializeComponent();

NotifyIcon.xaml

<MenuItem Header="Recent Timers" Name="MIRecent" ItemsSource="{Binding RecentTimers, UpdateSourceTrigger=PropertyChanged}"/>

NotifyIcon.xaml.cs

DataContext = DataStore.DATA_STORE;
InitializeComponent();

所以一切都在開始時正確綁定,但是當刪除TimerType時, PropertyChangedEventHandler始終為NULL。 我認為這是一個DataContext問題,但我很確定我現在有DataContext和所有Bindings正確嗎?

單例實例創建

private static readonly DataStore Instance = new DataStore();

private DataStore() { }

public static DataStore DATA_STORE
{
    get { return Instance; }
    set { }
}

不幸的是,通過使用Take (或任何LINQ方法),您可以獲得直接的IEnumerable 當您綁定它時,沒有INotifyCollectionChanged因此對集合的更改不會導致UI更新。

由於缺少INotifyCollectionChanged ,因此沒有真正的解決方法。 最好的辦法是在添加/刪除項目以強制UI重新計算IEnumerable時,針對“子集”屬性引發PropertyChanged

您可以使用CollectionView解決此問題

public class MyViewModel
{
    CollectionView _mostRecentDocuments;

    public MyViewModel()
    {
        Documents = new ObservableCollection<Document>();
        _mostRecentDocuments = new CollectionView(Documents);
        _mostRecentDocuments .Filter = x => Documents.Take(5).Contains(x);
    }

    public ObservableCollection<Document> Documents { get; private set; }    

    public CollectionView MostRecentDocuments
    {
        get 
        {
            return _mostRecentDocuments;
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM