在我的带有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);
}
需要帮助来解决它..!
答案 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();
}
解决问题..