我在数据网格中遇到了大量的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