これは長いポストになるでしょうし、私はすでにタイトルを謝っています。私は自分の問題にラベルを付ける方法がわかりません。WPF with Entity Framework usercontrolのdatacontextを使ったCRUD操作
私の質問に直接関係はありませんが、Entity Framework(コードファースト)を使用してWPFアプリケーションを構築していることがわかります。どちらも私はかなり新しいです。私は簡単な問題、小さな問題のプロトタイプを次のように実行しました:
私は2つのモデル、FastFoodとPersonを持っています。人にはファーストフードのお気に入りがあり、ファーストフードには関連する人がいます(1対多)。
public class FastFood
{
/// <summary>
/// Id of entity
/// </summary>
public int Id { get; set; }
/// <summary>
/// Name of entity
/// </summary>
public string Name { get; set; }
/// <summary>
/// Person this food preference belongs to
/// </summary>
public Person Person { get; set; }
/// <summary>
/// Key value of person this food preference belongs to
/// </summary>
public int PersonId { get; set; }
/// <summary>
/// A fast food chain
/// </summary>
public FastFood() { }
}
public class Person
{
/// <summary>
/// Entity Id of this person
/// </summary>
public int Id { get; set; }
/// <summary>
/// Name of this person
/// </summary>
public string Name { get; set; }
/// <summary>
/// Fast food favorites for this person
/// </summary>
public IList<FastFood> Favorites { get; set; }
/// <summary>
/// A person
/// </summary>
public Person() { Favorites = new List<FastFood>(); }
}
私のテーブルはEFで完璧に作成され、すべてがうまくいきます。私の状況は次のとおりです(サンプルデータあり):
public FoodContext() : base("Food")
{
if(!Database.Exists())
Database.SetInitializer(new FoodInit());
}
/// <summary>
/// Table for person(s)
/// </summary>
public DbSet<Person> People { get; set; }
/// <summary>
/// Table for fast foods
/// </summary>
public DbSet<FastFood> FastFoods { get; set; }
}
class FoodInit : DropCreateDatabaseAlways<FoodContext>
{
protected override void Seed(FoodContext context)
{
Person Bill = new Person() { Name = "Bill" };
FastFood GCoffee = new FastFood() { Name = "Gobias Industries" };
FastFood BananaStand = new FastFood() { Name = "Banana Stand" };
Bill.Favorites.Add(GCoffee);
Bill.Favorites.Add(BananaStand);
context.People.Add(Bill);
}
}
これはすべてうまくいきます。今すぐ簡単なGUIが来ます。
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public CollectionViewSource personViewSource;
public ObservableCollection<Person> People { get; set; }
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
{
System.Windows.Data.CollectionViewSource personViewSource = ((System.Windows.Data.CollectionViewSource)(this.FindResource("personViewSource")));
// Load data by setting the CollectionViewSource.Source property:
using(var context = new FoodContext())
{
context.People.Include("Favorites").Load();
People = new ObservableCollection<Person>(context.People.Local);
personViewSource.Source = People;
}
}
}
}
XAML
<Window.Resources>
<CollectionViewSource x:Key="personViewSource" d:DesignSource="{d:DesignInstance {x:Type local:Person}, CreateList=True}"/>
</Window.Resources>
<ScrollViewer>
<WrapPanel x:Name="PatientWrapPanel" DataContext="{StaticResource personViewSource}">
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel>
<local:PersonControl/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel IsItemsHost="True"></WrapPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</WrapPanel>
</ScrollViewer>
は、だから私はWrapPanelに人のコレクションを結合しています。 PersonControlにはカスタムコントロールPersonControlがあります。 XAMLで
/// <summary>
/// Interaction logic for PersonControl.xaml
/// </summary>
public partial class PersonControl : UserControl
{
public PersonControl()
{
InitializeComponent();
}
}
::人のコントロールは以下のように定義FoodChooserは、追加のカスタムユーザーコントロールである
<UserControl x:Class="WpfEntityExample.PersonControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfEntityExample"
mc:Ignorable="d" Background="White" Margin="5" Width="225" Height="240">
<Grid>
<Grid x:Name="grid1" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Label Content="Id:" Grid.Column="0" HorizontalAlignment="Left" Margin="3" Grid.Row="0" VerticalAlignment="Center"/>
<TextBox x:Name="idTextBox" Grid.Column="1" HorizontalAlignment="Left" Height="23" Margin="3" Grid.Row="0" Text="{Binding Id, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" VerticalAlignment="Center" Width="120"/>
<Label Content="Name:" Grid.Column="0" HorizontalAlignment="Left" Margin="3" Grid.Row="1" VerticalAlignment="Center"/>
<TextBox x:Name="nameTextBox" Grid.Column="1" HorizontalAlignment="Left" Height="23" Margin="3" Grid.Row="1" Text="{Binding Name, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" VerticalAlignment="Center" Width="120"/>
</Grid>
<local:FoodChooser DataContext="{Binding Favorites}" HorizontalAlignment="Left" Margin="10,79,0,0" VerticalAlignment="Top"/>
</Grid>
。 XAMLで
/// <summary>
/// Interaction logic for FoodChooser.xaml
/// </summary>
public partial class FoodChooser : UserControl
{
public FoodChooser()
{
InitializeComponent();
}
private void addButton_Click(object sender, RoutedEventArgs e)
{
//What goes here?
}
private void removeButton_Click(object sender, RoutedEventArgs e)
{
//What goes here?
}
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
//Do not load your data at design time.
if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
{
//Load your data here and assign the result to the CollectionViewSource.
System.Windows.Data.CollectionViewSource myCollectionViewSource = (System.Windows.Data.CollectionViewSource)this.Resources["fastFoodViewSource"];
myCollectionViewSource.Source = this.DataContext;
}
}
}
:
<UserControl x:Class="WpfEntityExample.FoodChooser"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WpfEntityExample"
mc:Ignorable="d"
d:DesignHeight="160" d:DesignWidth="200" Loaded="UserControl_Loaded">
<UserControl.Resources>
<CollectionViewSource x:Key="fastFoodViewSource" d:DesignSource="{d:DesignInstance {x:Type local:FastFood}, CreateList=True}"/>
</UserControl.Resources>
<Grid DataContext="{StaticResource fastFoodViewSource}" Width="200" Height="160">
<ListView x:Name="fastFoodListView" ItemsSource="{Binding}" Margin="0,0,10,45" SelectionMode="Single">
<ListView.ItemContainerStyle>
<Style>
<Setter Property="Control.HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="Control.VerticalContentAlignment" Value="Stretch"/>
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView>
<GridViewColumn x:Name="nameColumn" Header="Name" Width="140">
<GridViewColumn.CellTemplate>
<DataTemplate>
<ComboBox SelectedValue="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedValuePath="Content" SelectionChanged="ComboBox_SelectionChanged">
<ComboBoxItem>Gobias Industries</ComboBoxItem>
<ComboBoxItem>Banana Stand Inc.</ComboBoxItem>
<ComboBoxItem>Bob's Burgers</ComboBoxItem>
</ComboBox>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView>
</ListView.View>
</ListView>
<Button x:Name="removeButton" Content="Remove" IsEnabled="{Binding ElementName=foodBox, Path=SelectedItems.Count}" HorizontalAlignment="Left" Margin="115,130,0,0" VerticalAlignment="Top" Width="75" Click="removeButton_Click"/>
<Button x:Name="addButton" Content="Add" HorizontalAlignment="Left" Margin="10,130,0,0" VerticalAlignment="Top" Width="75" Click="addButton_Click"/>
</Grid>
私の質問は、私は人(複数可)お気に入りから新しいファーストフード項目を追加および削除する方法を私FoodChooserからでしょうか?私はコンボボックスからの更新を理解しています。これは、送信されたオブジェクトをFastFoodとしてキャストし、EFを通して再保存するという単純な問題であるためです。しかし、それらを親Personに関連させながら、どのようにFastFood項目を追加および削除し、GUIを更新することができますか? WPFのDataBindingと標準的な操作手順に欠けているものがありますか?数時間の実験から、データベース内の値を実際に更新することなく、GUIでの更新やGUIでの更新なしでデータベース内の変更を正常に実行できるようになりました。
もう一度、長い投稿と特定の問題を申し訳ありません。ソリューションが提供されるだけでなく、WPFとEntity Frameworkを組み合わせて使用する場合のチュートリアルに役立つリソースがあれば、さらに感謝します。私は両方を学ぼうとしていましたが、一緒に使用されている2つのリソースについては良いリソースが見つかりませんでした(基本的なMicrosoft NorthWindの例に加えて)。
あなたの最初の行について詳しく説明できますか? WPFコマンドを使用することを意味しますか? コントロールを削除し、ロジックを親Personコントロールに戻しました。何らかの理由で見つけられないという基本的な質問がもう1つあります。どのようにコードの背後にあるPersonのインスタンスにアクセスするのですか?上記のコードでは、 "person.RemoveFavorites ..."と言っています。DataContextからそのオブジェクトを取得する標準MVVM/WPFの方法は何ですか? ありがとうございます。 – Phrank
Pfff。私はあなたが人を得たところを見ます。私はもっと寝る必要があります.... – Phrank
MVVMについての情報は編集を参照してください。 – Emad