我在數據網格中遇到了大量的ComboBoxes問題。 真的想要一些幫助,我想我已經被研究的數量和我嘗試過的東西弄糊塗了。這真的應該很簡單,所以我必須錯過一些東西。CollectionViewSource不用PropertyChanged更新
簡化問題
我在XAML中使用CollectionViewSource,在C#中設置一類是頁面的DataContext的是CollectionViewSource到一個ObservableCollection源。 將項目添加到集合不會更新包含顯示視圖源的DataGridComboBox列。 見線以下的詳細
概述
我有一個WPF頁面上有一個數據網格。 頁面的數據上下文設置爲視圖模型。 viewModel包含兩個可觀察的集合。一個用於裝備和一個用於地點。 每個裝備都有一個位置。 這些從代碼第一EF數據庫填充,但我相信這個問題是高於該級別。
datagrid是每個設備一行。位置列需要是可供選擇的組合框,允許用戶更改位置。
我可以獲取位置組合框的唯一方法是將其綁定到單獨的集合視圖源。
問題
看來,如果頁面加載事件發生的視圖模型前填充的ObservableCollection那麼locationVwSrc將是空的,屬性更改事件不會得到這個改變。
實現簡短版本 頁面有一個在xaml中定義的集合viewSource。
Loaded="Page_Loaded"
Title="EquipRegPage">
<Page.Resources>
<CollectionViewSource x:Key="locationsVwSrc"/>
</Page.Resources>
datagrid是用xaml定義的。
<DataGrid x:Name="equipsDataGrid" RowDetailsVisibilityMode="VisibleWhenSelected" Margin="10,10,-118,59"
ItemsSource="{Binding Equips}" EnableRowVirtualization="True" AutoGenerateColumns="False">
在XAML定義的組合框柱
<DataGridComboBoxColumn x:Name="locationColumn" Width="Auto" MaxWidth="200" Header="Location"
ItemsSource="{Binding Source={StaticResource locationsVwSrc}, UpdateSourceTrigger=PropertyChanged}"
DisplayMemberPath="Name"
SelectedValueBinding="{Binding Location}"
設置爲視圖模型
public partial class EquipRegPage : Page
{
EquipRegVm viewModel = new EquipRegVm();
public EquipRegPage()
{
InitializeComponent();
this.DataContext = viewModel;
}
Loaded事件頁面上下文設置上下文
private void Page_Loaded(object sender, RoutedEventArgs e)
{
// Locations View Source
System.Windows.Data.CollectionViewSource locationViewSource =
((System.Windows.Data.CollectionViewSource)(this.FindResource("locationsVwSrc")));
locationViewSource.Source = viewModel.Locations;
// Above does not work if the viewmodel populates these after this call, only works if its populated prior.
//TODO inotifypropertychanged not correct? This occurs before the viewmodels loads, and doesn't display.
// Therefore notify property changes aren't working.
// Using this as cheat instead instead works, i beleive due to this only setting the source when its full
//viewModel.Db.Locations.Load();
//locationViewSource.Source = viewModel.Db.Locations.Local;
//locationViewSource.View.Refresh();
}
的ViewModel類以及它如何加載s
public class EquipRegVm : DbWrap, INotifyPropertyChanged
{
/// <summary>
/// Event triggered by changes to properties. This notifys the WPF UI above which then
/// makes a binding to the UI.
/// </summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Notify Property Changed Event Trigger
/// </summary>
/// <param name="propertyName">Name of the property changed. Must match the binding path of the XAML.</param>
void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
public ObservableCollection<Equip> Equips { get; set; }
public ObservableCollection<Location> Locations { get; set; }
public EquipRegVm() : base()
{
Load();
}
/// <summary>
/// Load the data from the Model.
/// </summary>
public async void Load() //TODO async an issue?
{
// EQUIPMENT
ObservableCollection<Equip> eqList = new ObservableCollection<Equip>();
var eqs = await (from eq in Db.Equips
orderby eq.Tag
select eq).ToListAsync();
foreach(var eq in eqs)
{
eqList.Add(eq);
}
Equips = eqList;
RaisePropertyChanged("Equips");
// LOCATIONS
ObservableCollection<Location> locList = new ObservableCollection<Location>();
var locs = await (from l in Db.Locations
orderby l.Name
select l).ToListAsync();
foreach (var l in locs)
{
locList.Add(l);
}
Locations = locList;
RaisePropertyChanged("Locations");
}
}
這當然解決了眼前的問題。謝謝@AnjumSKhan。李坎貝爾提出了一些好點,我當然有興趣向他學習更多。 – Asvaldr
是的,這將解決問題,但通過添加更多不必要的代碼。 –
我同意李,如果你有任何更多的見解我熱衷學習。請參閱我對解決方案的最新評論。 – Asvaldr