WPF EFのエンティティ値が変更されたときの自動バインディング

c# data-binding entity-framework entity-framework-core wpf

質問

私はEntity Frameworkの初心者です。私はそれを学びたいと思っています。

私は公式文書にある演習を修正しようとしていました。私は父親のリストと息子のリストを持っていたいと思います。すべての息子は、コンボボックスメニューから選択された父親を持っていなければなりません。

今私はそれを行うことができますが、私が父親を追加する場合、私は父親のリストやコンボボックスには見ません。私が息子を加えると、私は息子のリストにその息子は見えません。

私がプログラムを閉じて再度開くと、以前に追加された父と息子を正しく見ています。

どのように私は自動的にコンボボックスとリストビューのデータをアップグレードできますか?

私はリフレッシュする関数を呼び出すのが好きではない、私は自動的にデータベース内の何かを変更するときに更新をしたいと思います。

私のプロジェクトは3つのファイルで構成されています:

MainWindow.xaml

<Window x:Class="EF7Fam.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:EF7Fam"
        mc:Ignorable="d"
        Loaded="Page_Loaded"
        Title="MainWindow" Height="350" Width="550">

    <Grid>
        <StackPanel Orientation="Horizontal">
            <StackPanel Width="263" Margin="3 0 3 0">
                <TextBox Name="NewFT"></TextBox>
                <Button Click="Add_Click">Add</Button>
                <ListView Name="Fathers">
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" />
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>
            </StackPanel>
            <StackPanel Width="263" Margin="3 0 3 0">
                <TextBox Name="NewSN"></TextBox>
                <ComboBox Name="FT" DisplayMemberPath="Name" SelectedValuePath="FTId"/>
                <Button Click="Add_SN_Click">Add</Button>
                <ListView Name="Sons">
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" />
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>
            </StackPanel>
        </StackPanel>
    </Grid>
</Window>

MainWindow.xaml.cs

using Microsoft.Data.Entity;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace EF7Fam
{
    /// <summary>
    /// Logica di interazione per MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            using (var db = new Family())
            {
                db.Database.Migrate();
            }
        }

        private void Page_Loaded(object sender, RoutedEventArgs e)
        {
            using (var db = new Family())
            {
                Fathers.ItemsSource = db.Fathers.ToList();
                Sons.ItemsSource = db.Sons.ToList();
                FT.ItemsSource = db.Fathers.ToList();
            }
        }

        private void Add_Click(object sender, RoutedEventArgs e)
        {
            using (var db = new Family())
            {
                var ft = new Father { Name = NewFT.Text };
                db.Fathers.Add(ft);
                db.SaveChanges();
            }
        }

        private void Add_SN_Click(object sender, RoutedEventArgs e) 
        {
            using (var db = new Family())
            {
                var sn = new Son { Name = NewSN.Text, FTId = Int32.Parse(FT.SelectedValue.ToString()) };
                db.Sons.Add(sn);
                db.SaveChanges();
            }
        }
    }
}

Model.cs

using System;
using Microsoft.Data.Entity;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Runtime.CompilerServices;

namespace EF7Fam
{

    public class Family : DbContext
    {
        public DbSet<Father> Fathers { get; set; }
        public DbSet<Son> Sons { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlite($"Filename=Family.db");
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Father>()
                .Property(b => b.Name)
                .IsRequired();
        }
    }

    public class Father : INotifyPropertyChanged
    {
        [Key]
        public int FTId { get; set; }
        public string Name { get; set; }

        public List<Son> Sons { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }


    public class Son : INotifyPropertyChanged
    {
        [Key]
        public int SNId { get; set; }
        public string Name { get; set; }

        public int FTId { get; set; }
        public Father Father { get; set; }

        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

私はこのサイトとウェブで何度も見たが、解決策を見つけることはなかった。

誰かが私が私が間違っていることを私に教えてもらう手助けができれば、私はとても感謝しています。

ありがとさよなら、

エンリコ

人気のある回答

コントロールをDbSetsバインドするには、これを行う必要があります。

private void Page_Loaded(object sender, RoutedEventArgs e)
{
        using (var db = new Family())
        {
            db.Fathers.Load();
            Fathers.ItemsSource = db.Fathers.Local;
            db.Sons.Load();
            Sons.ItemsSource = db.Sons.Local;
            FT.ItemsSource = db.Fathers.Local;
        }
}

呼び出しLoadあなたはメモリとに既存のオブジェクトをロードしようとしている方法DbSet<TEntity>.Localプロパティは、あなたを与えるだろうObservableCollection<TEntity>すべて含まれているUnchangedModifiedおよびAdded現在で追跡されたオブジェクトDbContext与えられたためDbSetObservableCollectionを追加または削除Removeと、 DbSet対応するAdd / Removeも実行されます。

ビューで必要なすべての操作を実行した後に変更を保存する必要がある場合は、コマンドを定義するか、ビュー内のボタンのクリックイベントをオーバーライドして、コンテキストのSaveChangesメソッドを呼び出すことができます。

  private void SaveChanges_Click(object sender, RoutedEventArgs e) 
  {
        using (var db = new Family())
        {
            db.SaveChanges();
        }
  }

更新

今私はあなたがEF7を使用しているのを見ましたが、私はこのバージョンのすべての変更を認識していませんが、たくさんあることを伝えることができます。私はそれについて尋ねた質問を見つけ、まだ答えられていません。

ドキュメントをもっと掘り下げる私は解決策を見つけたと思うが、本当は好きではないが、 Loadプロパティが現れるまではうまくいくかもしれない。 EFのドキュメントによれば、これを行うことができます:

private void Add_Click(object sender, RoutedEventArgs e)
{
        using (var db = new Family())
        {
            var ft = new Father { Name = NewFT.Text };
            db.Fathers.Add(ft);
            db.SaveChanges();
            Fathers.ItemsSource = db.Fathers.ToList();
        }
 }

私がより良い解決策を見つけたら、私はあなたに知らせるでしょう。



Related

ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ
ライセンスを受けた: CC-BY-SA with attribution
所属していない Stack Overflow
このKBは合法ですか? はい、理由を学ぶ