0

MVVMパターンプロジェクトを使用したSilverlight5には、リストボックスが1つあります。entityframeworkを使用してデータをリストボックスにロードします。最初に、エンティティフレームワークモデルを使用して、すべてのデータが必ずリストボックスに読み込まれます。しかし、新しいデータを追加すると、リストボックスに新しく追加された値が表示されません。しかし、新しく追加された価値はエンティティで利用可能です。何が問題ですか?これを達成するために私がしなければならないこと。

リストボックス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;
}

これらの依存関係をすべて排除するには、まず、リファクタリングを実行し、インターフェイスを抽出し、リポジトリを作成し、制御の反転を実装する必要があると思います。

いくつかのコードを手伝いましょう:(まず、エンティティコンテキストをどのように実装しているかわかりません。エンティティフレームワークのコードファーストアプローチが非常に気に入っています。(一種の)デモンストレーションに使用します)

あなたのオブジェクトはおそらくこのように見えます。

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メソッドを含めるべきではありません。代わりに、それらを(そのインターフェースを備えた)リポジトリー実装に抽出しましょう。

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コンテナーを実装します。これを行うには、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

Haiは今、これを修正しました。ListBox_loaded()イベントでDataContextを記述します。

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

問題が解決しました..

于 2013-01-28T13:47:24.713 に答える