0

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

列表框 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>

视图模型代码:

    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);

        }

需要帮助解决它..!

4

2 回答 2

2

编辑:在这段代码中, saveChanges() 没有在任何地方实现。它应该适合您的需求。

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

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

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

让我帮您编写一些代码:(首先,我不确定您是如何实现实体上下文的,我非常喜欢 Entity Framework 的 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 现在会简单得多。为了使双向绑定正确及时更新,我们将实现 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 Container,以便将所有这些部分连接在一起。为此,您必须重写 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();
  }
}
于 2013-01-28T12:41:52.007 回答
0

海刚才我修复了这个.. 在 ListBox_loaded() 事件中编写 DataContext。

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

问题解决了..

于 2013-01-28T13:47:24.713 回答