【问题标题】:EF Code First binding to listboxEF Code First 绑定到列表框
【发布时间】:2011-11-23 14:40:48
【问题描述】:

如果有人能告诉我如何将列表框绑定到实体框架(EF 代码优先),我将不胜感激。

我正在使用 prism 和 mef。有两种视图,一种带有按钮,另一种带有列表框。 (每个都在自己的棱镜区域)。 通过单击按钮,我创建了一个新的 Employee 对象并通过实体框架将其插入到数据库中。

问题是我的列表框没有向我显示列表中新添加的 Employee 对象。应该进行哪些更改才能使其正常工作?

部分代码:

主视图:

    <Grid>
    <StackPanel>
        <TextBlock Text="Hello From MainView (Core Module)" />
        <ListBox ItemsSource="{Binding Employees, Mode=TwoWay}">
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding FirstName}" />
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </StackPanel>
</Grid>

MainViewModel:

namespace EmployeeViewer.Core.ViewModels
{
  [Export]
  [PartCreationPolicy(CreationPolicy.NonShared)]
  public class MainViewModel : NotificationObject
  {
    private IUnitOfWork _UnitOfWork;

[ImportingConstructor]
public MainViewModel(IUnitOfWork unitOfWork) // IEventAggregator eventAggregator
{
  this._UnitOfWork = unitOfWork;

  Init();
}

private void Init()
{
  this.Employees = new ObservableCollection<Employee>(_UnitOfWork.EmployeeRepository.Get());
  //this.Employees = new BindingList<Employee>(_UnitOfWork.EmployeeRepository.Get().ToList());
}

public ObservableCollection<Employee> Employees { get; set; }
//public BindingList<Employee> Employees { get; set; }

} }

从 GenericRepository 获取方法:

    public virtual IEnumerable<TEntity> Get(
  Expression<Func<TEntity, bool>> filter = null,
  Func<IQueryable<TEntity>,
  IOrderedQueryable<TEntity>> orderBy = null,
  string includeProperties = "")
{
  IQueryable<TEntity> query = _DbSet;

  if (filter != null)
  {
    query = query.Where(filter);
  }

  foreach (var includeProperty in includeProperties.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
  {
    query = query.Include(includeProperty);
  }

  if (orderBy != null)
  {
    return orderBy(query).AsEnumerable();//.ToList();
  }
  else
  {
    return query.AsEnumerable();//.ToList();
  }
}

通过另一个区域和视图中的 ICommand(实现为 RelayCommand),我首先创建一个新的 Employee 对象并将其插入到实体框架代码中。

public ICommand AddEmployeeCommand
{
  get { return _AddEmployeeCommand; }
}

private void AddEmployee()
{
  _UnitOfWork.EmployeeRepository.Insert(new Employee() { FirstName = "Test", LastName = "Via cmd" });
  _UnitOfWork.Save();
}

【问题讨论】:

    标签: wpf entity-framework data-binding mvvm


    【解决方案1】:

    Bing.com搜索后发现EF有一个Local属性。

    如果您正在寻找解决方案,我就是这样做的:

    我向我的 GenericRepository 添加了一个新方法:

    public virtual ObservableCollection<TEntity> GetSyncedEntityItems()
    {
      return _DbSet.Local;
    }
    

    这是最重要的部分:.Local 为您提供与 EF 同步的 ObservableCollection!。

    在我的 ViewModel 中我这样做:

    this.Employees = _UnitOfWork.EmployeeRepository.GetSyncedEntityItems();
    

    向 EF 添加新员工将导致我的其他视图更新:

    private void AddEmployee()
    {
      _UnitOfWork.EmployeeRepository.Insert(new Employee() { FirstName = "Test", LastName = "Via cmd" });
      _UnitOfWork.Save();
    }
    

    我不知道这是否是最好的解决方案,如果有更好的选择,请告诉我!

    【讨论】:

      【解决方案2】:

      你需要触发 INotifyPropertyChanged.PropertyChanged,我认为 NotificationObject 会有一个很好的方法来做到这一点。

      当您的 Employees 属性从 null 变为包含项目的列表时,您的 View 需要得到通知以便更新。

      一旦Employees 属性不为null,添加的新项目将自动更新视图(ObservableCollection 的b/c)。

      【讨论】:

      • 那么 ObservableCollection 将通过 EF 自动通知添加了一个项目?因为我无法将新对象添加到 Listbox 或 Employees 属性,因为它们在另一个视图中(可能在另一个 .dll 文件中)。
      • 添加到您的员工存储库不会自动添加到您的 ObservableCollection。您用于 ObservableCollection 的构造函数只是一种一次性复制机制。
      • 但是我可以添加其他吗?在按钮所在的视图/视图模型中,我无权访问其他视图/视图模型来访问员工属性或列表框。关于如何做到这一点的任何建议?
      • 在 prism 中有一个事件聚合器,这允许视图模型之间的通信,但保持它们松散耦合。下面是一个例子:msdn.microsoft.com/en-us/library/ff921122(v=pandp.20).aspx 我会让员工通过事件。
      猜你喜欢
      • 1970-01-01
      • 2011-09-27
      • 2023-04-03
      • 1970-01-01
      • 1970-01-01
      • 2011-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多