Listbox不显示带有Entity Framework的silverlight mvvm中的更新/新添加的值

时间:2013-01-28 10:49:01

标签: silverlight entity-framework mvvm

在我的带有MVVM模式项目的Silverlight5中,我有一个列表框。 我使用entityframework将数据加载到列表框。最初,所有数据都使用实体框架模型加载到列表框中。 但是,如果我添加新数据,列表框不会显示新添加的值。但新增加的价值可在实体中获得。 问题是什么?我必须做些什么来实现这一目标。

Listbox xaml编码:

<ListBox ItemsSource="{Binding Projects,Mode=TwoWay}" SelectedItem="{Binding Project,Mode=TwoWay}" SelectionMode="Single" >
                        <ListBox.ItemsPanel>
                            <ItemsPanelTemplate>
                                <!--<StackPanel Orientation="Horizontal" />-->

                            </ItemsPanelTemplate>
                        </ListBox.ItemsPanel>
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <Border BorderBrush="Gray" Margin="2,2,2,2"  BorderThickness="0">
                                    <StackPanel Orientation="Vertical" >
                                        <TextBlock Text="{Binding ProjectName,Mode=TwoWay}"/>
                                    </StackPanel>
                                </Border>
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                    </ListBox>

Viewmodel代码:

    private IEnumerable<Project> projects;
        private Project project;
        private Customer customer;


        PartsDomainContext _context;
        public IEnumerable<Project> Projects
        {
            get
            {
                return projects;
            }
            set
            {
                projects= value;
                if (projects != null)
                {
                    OnPropertyChanged("Projects");
                    Project = projects.FirstOrDefault();
                    OnPropertyChanged("Project");
                }
            }
        }
public Project Project
        {
            get
            { 
                return project;
            }
            set
            {
                project=value;
                OnPropertyChanged("Project");
                if (project != null)
                {   

                    Customer = project.CustomerProjects.FirstOrDefault().Customer;
                    OnPropertyChanged("Customer");
                }
            }
        }
public ProjectListViewModel()
        {
            GetProjectList(ActiveData.Instance.userid);
        }
public void GetProjectList(int userid)
        {
            _context = new PartsDomainContext();
            OnPropertyChanged("Projects");
            _context.Load(_context.GetProjectListQuery(ActiveData.Instance.userid), Param =>
                {
                    if (!Param.HasError)
                    {
                        Projects = Param.Entities;
                        OnPropertyChanged("Projects");
                    }
                }, null);
        }


public void GetProjectList(int userid)
        {
            _context = new PartsDomainContext();
            OnPropertyChanged("Projects");
            _context.Load(_context.GetProjectListQuery(ActiveData.Instance.userid), Param =>
                {
                    if (!Param.HasError)
                    {
                        Projects = Param.Entities;
                        OnPropertyChanged("Projects");
                    }
                }, null);

        }

需要帮助来解决它..!

2 个答案:

答案 0 :(得分:2)

编辑:在此代码中,saveChanges()未在任何地方实现。它应该适应您的需求。

UPDATE2:我忘了提到如何从视图到viewmodel创建数据绑定。 这可以与UserControls一样使用。 UnityContainer将自动解析所有依赖项。在您的代码隐藏中,您将构造函数更改为:

public MainWindow(ProjectViewModel projectViewModel)
{
    this.DataContext = projectViewModel;
}

我认为首先你应该做一些重构,提取一些接口,创建一个存储库并实现控制反转,以消除所有这些依赖。

让我帮你一些代码: (首先,我不确定你是如何实现你的实体上下文的,我非常喜欢实体框架的Code First方法,我将使用(kindof)来演示)

您的对象可能看起来有点像这样。

public class Project
{
  public int UserId { get; set; }
  //...
}

然后你有你的上下文及其界面:

(这个非常简单,具有说明性,使用Code First,如上所述)

public interface IProjectContext
{
  DbSet<Project> Projects { get; set; }
}

public class ProjectContext : DbContext, IProjectContext
{
  public DbSet<Project> Projects { get; set; }
}

现在,您不应该在ViewModel上使用这些Get方法。相反,让我们将它们提取到一个Repository实现(带有它的接口)。

public interface IProjectRepository
{
  Project[] GetAll();
  Project[] GetByUser(int userId);
  void Add(Project project);
  void Remove(ProjectRepository project);
}

public class ProjectRepository : IProjectRepository
{
  private IProjectContext context;

  public ProjectRepository(IProjectContext context)
  {
    this.context = context;
  }

  public Project[] GetAll()
  {
    return context.Projects.ToArray();
  }

  public Project[] GetByUser(int userId)
  {
    return context.Projects.Where(p => p.UserId == userId).ToArray();
  }

  public void Add(Project project)
  {
    context.Projects.Add(project);
  }

  public void Remove(Project project)
  {
    context.Projects.Remove(project);
  }
}

现在,您的ViewModel将变得更加简单。并且为了使twoway绑定更新正确且准时,我们将实现INotifyPropertChanged

public class ProjectViewModel : INotifyPropertyChanged
{
  #region Property Changed
  public event PropertyChangedEventHandler PropertyChanged;
  protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
  {
    var handler = this.PropertyChanged;
    if (handler != null)
    {
      handler(this, e);
    }
  }
  protected void RaisePropertyChanged(String propertyName)
  {
    OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
  }
  #endregion

  private IProjectRepository projectRepository;
  private ICollection<Project> projects;
  private Project activeProject;

  public ICollection<Project> Projects
  {
    get { return projects; }
    set
    {
      projects = value;
      RaisePropertyChanged("Projects");
    }
  }

  public Project ActiveProject
  {
    get { return activeProject; }
    set
    {
      activeProject = value;
      RaisePropertyChanged("ActiveProject");
    }
  }

  public ProjectViewModel(IProjectRepository projectRepository)
  {
    this.projectRepository = projectRepository;
    Projects = projectRepository.GetAll();
    ActiveProject = Projects.FirstOrDefault();
  }
}

我会在App.xaml.cs中实现Unity容器,以便将所有这些部分连接在一起。为此,您必须覆盖OnStartup并注册上述类型。

public partial class App : Application
{
  protected override OnStartup(StartupEventArgs e)
  {
    private IUnityContainer container = new UnityContainer();
    container.RegisterType<IProjectRepository,ProjectRepository>(new ContainerControlledLifetimeManager());
    container.RegisterType<IProjectContext,ProjectContext>(new ContainerControlledLifetimeManager());
    MainWindow window = container.Resolve<MainWindow>();
    window.Show();
  }
}

答案 1 :(得分:0)

Hai刚刚解决了这个问题..用ListBox_loaded()事件编写DataContext。

private void ListBox_Loaded(object sender, RoutedEventArgs e)
        {
            DataContext = new UrViewModel();
        } 

解决问题..