Results 1 to 3 of 3

Thread: Trouble with persisting data from MVVM to Entity Framework using WPF binding

  1. #1
    Xipooo is offline VB.NET Forum Newbie
    .NET Framework
    .NET 4.5
    Join Date
    Jan 2014
    Posts
    3
    Reputation
    0

    Trouble with persisting data from MVVM to Entity Framework using WPF binding

    Here is my VM class:


    Code:
    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

    Here is my XAML:
    Code:
    <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>



    The users datagrid works perfectly fine. I'm having trouble with a master-detail setup on my "Weekly Settings" tab.


    My ObjectDataProvider for the listbox gets an ObservableCollection of Settings Objects through the "WeekList" method of my VM. I set the datacontext of my detail grid to the SelectedItem of that listbox. But when I try to save any changes made to the details, they don't persist back to the Entity Framework when I perform a "SaveChanges".


    I could really use some help here.

  2. #2
    Xipooo is offline VB.NET Forum Newbie
    .NET Framework
    .NET 4.5
    Join Date
    Jan 2014
    Posts
    3
    Reputation
    0
    Hmmm... is the question not phrased correctly or are there not enough people familiar with WPF binding to help me?

  3. #3
    Xipooo is offline VB.NET Forum Newbie
    .NET Framework
    .NET 4.5
    Join Date
    Jan 2014
    Posts
    3
    Reputation
    0
    Well I was able to receive the answer from elsewhere but thank you to anyone who was trying.
    The solution was that I needed to drop the ObjectDataContext's and instead use more properties.
    I created a SelectedYear property as an integer and a WeekList property as an observablecollection of schedulesetting. The Selected year property was bound as the selecteditem of my combobox, and the weeklist had it's getter use the selected week property in a lambda expression to return a filtered list of weeks.
    I had to also change it so the datacontexts were set on both the combobox and listbox to the VM. In hindsight, that part should have been obvious.

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •