数据更改不会持久地返回到MVVM应用程序上的Entity Framework

时间:2014-01-29 16:53:59

标签: wpf vb.net entity-framework xaml mvvm

我会先发布我的代码,然后问我的问题。

XAML:

<Window
    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:FootballPool" mc:Ignorable="d" x:Class="MainWindow"
    xmlns:system="clr-namespace:System;assembly=mscorlib"
    Title="MainWindow" Height="350" Width="525" Margin="5">
    <Window.Resources>
        <local:MainWindowVM x:Key="ViewModel" />
        <ObjectDataProvider x:Key="YearList"
                            ObjectType="{x:Type local:MainWindowVM}"
                            MethodName="YearList" />
        <ObjectDataProvider x:Key="WeekList"
                            ObjectType="{x:Type local:MainWindowVM}"
                            MethodName="WeekList">
            <ObjectDataProvider.MethodParameters>
                <system:Int32>0</system:Int32>
            </ObjectDataProvider.MethodParameters>
        </ObjectDataProvider>
    </Window.Resources>
    <Grid>
        <TabControl Margin="0,0,0,37">
            <TabItem Header="Standings">
                <Grid Background="#FFE5E5E5"/>
            </TabItem>
            <TabItem Header="Users">
                <Grid Background="#FFE5E5E5">
                    <DataGrid
                        x:Name="dgUsers"
                        DataContext="{Binding Source={StaticResource ViewModel}}"
                        ItemsSource="{Binding Users, Mode=TwoWay}" AutoGenerateColumns="False"
                        IsSynchronizedWithCurrentItem="True"
                        >
                        <DataGrid.Columns>
                            <DataGridTextColumn Binding="{Binding FirstName}" ClipboardContentBinding="{x:Null}" Header="First Name"/>
                            <DataGridTextColumn Binding="{Binding LastName}" ClipboardContentBinding="{x:Null}" Header="Last Name"/>
                            <DataGridTextColumn Binding="{Binding Email}" ClipboardContentBinding="{x:Null}" Header="Email"/>
                            <DataGridTextColumn Binding="{Binding Password}" ClipboardContentBinding="{x:Null}" Header="Password"/>
                        </DataGrid.Columns>

                    </DataGrid>
                </Grid>
            </TabItem>
            <TabItem Header="Weekly Settings">
                <Grid Background="#FFE5E5E5">
                    <Grid x:Name="Grid1" HorizontalAlignment="Left" VerticalAlignment="Top" Background="#FFC8C8C8" Margin="238,27,0,0" DataContext="{Binding SelectedItem, ElementName=listBox}">
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="Auto"/>
                        </Grid.ColumnDefinitions>
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="Auto"/>
                        </Grid.RowDefinitions>
                        <Label Content="Year:" Grid.Column="0" HorizontalAlignment="Left" Margin="3" Grid.Row="0" VerticalAlignment="Center"/>
                        <TextBox x:Name="Year" Grid.Column="1" HorizontalAlignment="Left" Height="24" Margin="3" Grid.Row="0" Text="{Binding Year, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" VerticalAlignment="Center" Width="120"/>
                        <Label Content="Week Number:" Grid.Column="0" HorizontalAlignment="Left" Margin="3" Grid.Row="1" VerticalAlignment="Center"/>
                        <TextBox x:Name="WeekNumberTextBox" Grid.Column="1" HorizontalAlignment="Left" Height="23" Margin="1" Grid.Row="1" Text="{Binding WeekNumber, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" VerticalAlignment="Center" Width="120"/>
                        <Label Content="Begin Date:" Grid.Column="0" HorizontalAlignment="Left" Margin="3" Grid.Row="2" VerticalAlignment="Center"/>
                        <DatePicker x:Name="BeginDateDatePicker" Grid.Column="1" HorizontalAlignment="Left" Margin="3" Grid.Row="2" SelectedDate="{Binding BeginDate, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" VerticalAlignment="Center"/>
                        <Label Content="End Date:" Grid.Column="0" HorizontalAlignment="Left" Margin="3" Grid.Row="3" VerticalAlignment="Center"/>
                        <DatePicker x:Name="EndDateDatePicker" Grid.Column="1" HorizontalAlignment="Left" Margin="3" Grid.Row="3" SelectedDate="{Binding EndDate, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" VerticalAlignment="Center"/>
                        <Label Content="Cost:" Grid.Column="0" HorizontalAlignment="Left" Margin="3" Grid.Row="4" VerticalAlignment="Center"/>
                        <TextBox x:Name="CostTextBox" Grid.Column="1" HorizontalAlignment="Left" Height="23" Margin="3" Grid.Row="4" Text="{Binding Cost, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" VerticalAlignment="Center" Width="120"/>

                    </Grid>
                    <Button x:Name="btnNewWeek" Content="New Week" HorizontalAlignment="Left" Height="23" Margin="384,192,0,0" VerticalAlignment="Top" Width="75"/>
                    <ComboBox x:Name="cboYear"
                              HorizontalAlignment="Left" Margin="94,14,0,0" 
                              VerticalAlignment="Top" Width="56"  
                              IsSynchronizedWithCurrentItem="True" 
                              ItemsSource="{Binding Mode=OneWay, Source={StaticResource YearList}}">
                        <ComboBox.SelectedItem>
                            <Binding Source="{StaticResource WeekList}"
                                     Path="MethodParameters[0]"
                                     BindsDirectlyToSource="True"
                                     UpdateSourceTrigger="PropertyChanged" />
                        </ComboBox.SelectedItem>
                    </ComboBox>
                    <ListBox x:Name="listBox" HorizontalAlignment="Left" Height="136" Margin="95,51,0,0" VerticalAlignment="Top" Width="55" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Source={StaticResource WeekList}}" DisplayMemberPath="WeekNumber" />
                    <Label Content="Year:" HorizontalAlignment="Left" Margin="27,10,0,0" VerticalAlignment="Top"/>
                    <Label Content="Week:" HorizontalAlignment="Left" Margin="27,51,0,0" VerticalAlignment="Top"/>
                </Grid>
            </TabItem>
        </TabControl>
        <Button Content="Save" HorizontalAlignment="Right" Height="27" Margin="0,0,5,5" VerticalAlignment="Bottom" Width="80" Click="Button_Click"/>
    </Grid>
</Window>

视图模型:

Imports System.Collections.ObjectModel
Imports System.ComponentModel
Imports System.Collections.Specialized

Public Class MainWindowVM
    Implements INotifyPropertyChanged
    Implements INotifyCollectionChanged

    Dim dbcontext As New FootballPoolEntities
    Private _Users As ObservableCollection(Of User)
    Private _Settings As ObservableCollection(Of ScheduleSetting)
    Public Property Users As ObservableCollection(Of User)
        Get
            Return _Users
        End Get
        Set(value As ObservableCollection(Of User))
            _Users = value
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Users"))
        End Set
    End Property
    Public Property Settings As ObservableCollection(Of ScheduleSetting)
        Get
            Return _Settings
        End Get
        Set(value As ObservableCollection(Of ScheduleSetting))
            _Settings = value
            RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs("Settings"))
        End Set
    End Property

    Public Sub New()
        _Users = New ObservableCollection(Of User)(dbcontext.Users.ToList)
        _Settings = New ObservableCollection(Of ScheduleSetting)(dbcontext.ScheduleSettings.ToList)
        AddHandler Users.CollectionChanged, AddressOf OnUsersCollectionChanged
        AddHandler Settings.CollectionChanged, AddressOf OnSettingsCollectionChanged
    End Sub

    Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged
    Public Event CollectionChanged(sender As Object, e As NotifyCollectionChangedEventArgs) Implements INotifyCollectionChanged.CollectionChanged

    Private Sub OnUsersCollectionChanged(sender As Object, e As NotifyCollectionChangedEventArgs)
        If e.Action = NotifyCollectionChangedAction.Add Then
            For Each item In e.NewItems
                dbcontext.Users.Add(item)
            Next
        End If
        If e.Action = NotifyCollectionChangedAction.Remove Then
            For Each item In e.OldItems
                dbcontext.Users.Remove(item)
            Next
        End If
    End Sub

    Private Sub OnSettingsCollectionChanged(sender As Object, e As NotifyCollectionChangedEventArgs)
        If e.Action = NotifyCollectionChangedAction.Add Then
            For Each item In e.NewItems
                dbcontext.ScheduleSettings.Add(item)
            Next
        End If
        If e.Action = NotifyCollectionChangedAction.Remove Then
            For Each item In e.OldItems
                dbcontext.ScheduleSettings.Remove(item)
            Next
        End If
    End Sub

    Public Sub SaveChanges()
        dbcontext.SaveChanges()
    End Sub
    Public Sub NewWeek()
        Dim newWeek As New ScheduleSetting
        Settings.Add(newWeek)
    End Sub

    Public Function WeekList(SelectedYear As Int32) As ObservableCollection(Of ScheduleSetting)
        If SelectedYear = 0 Then
            Return Nothing
            Exit Function
        End If
        Return New ObservableCollection(Of ScheduleSetting)(Settings.Where(Function(c) c.Year = SelectedYear).ToList)
    End Function

    Public Function YearList() As List(Of Int32)
        Return dbcontext.ScheduleSettings _
            .Select(Function(x) x.Year) _
            .Distinct.ToList()
    End Function
End Class

我遇到的问题是我的列表框通过“WeekList”方法和ObjectDataProvider填充了Settings对象。我的详细信息网格将其datacontext绑定到该列表框的SelectedItem。当我对数据进行更改时,当我执行savechanges时,它们不会持久地返回到Entity Framework。我是否遗漏了绑定中的某些内容,我是否应该以不同的方式处理Master-Detail?或者我的ViewModel中有什么需要添加的东西吗?

感谢有人提供的任何帮助。感谢。

1 个答案:

答案 0 :(得分:0)

我能够从其他地方收到答案,但感谢任何正在尝试的人。

解决方案是我需要删除ObjectDataContext,而是使用更多属性。

我创建了一个SelectedYear属性作为整数,并创建了一个WeekList属性作为schedulesetting的observablecollection。选定的年份属性被绑定为我的组合框的选择项,并且周列表让它的getter使用lambda表达式中的选定周属性来返回已过滤的周列表。

我还必须更改它,以便在组合框和列表框上为VM设置datacontexts。事后来看,那部分应该是显而易见的。