【发布时间】:2017-02-17 02:45:44
【问题描述】:
我在使用数据网格中的组合框时遇到了很多麻烦。 真的需要一些帮助,我想我已经被大量的研究和我尝试过的东西弄糊涂了。这真的应该很简单,所以我一定错过了一些东西。
简化问题
我在 xaml 中使用 CollectionViewSource,C# 将该 CollectionViewSource 的源设置为作为页面数据上下文的类中的 ObservableCollection。 将项目添加到集合不会更新包含显示视图源的 DataGridComboBox 列。 有关详细信息,请参见下面的行
概览
我有一个 WPF 页面,上面有一个数据网格。 该页面将其数据上下文设置为视图模型。 viewModel 包含两个可观察的集合。一个用于设备,一个用于位置。 每个装备都有一个位置。 这些是从代码优先的 EF 数据库中填充的,但我相信这个问题超出了那个级别。
数据网格是每个装备一行。 Location 列需要是一个可选择的组合框,允许用户更改 Location。
我可以完全填充位置组合框的唯一方法是将其绑定到单独的集合视图源。
问题
似乎如果页面加载事件发生在 ViewModel 填充 ObservableCollection 之前,那么 locationVwSrc 将为空,并且属性更改事件不会改变它。
实现短版 页面在 xaml 中定义了一个集合 viewSource。
Loaded="Page_Loaded"
Title="EquipRegPage">
<Page.Resources>
<CollectionViewSource x:Key="locationsVwSrc"/>
</Page.Resources>
数据网格是用 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;
}
加载事件设置上下文
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 类及其加载方式
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");
}
}
【问题讨论】:
标签: c# wpf xaml datagrid datagridcomboboxcolumn