PropertyChanged always null - silverlight-4.0

This is my MainPage.xaml :-
<UserControl x:Class="SilverlightPlainWCF.MainPage"
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"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" xmlns:my="clr-namespace:SilverlightPlainWCF.CustomersServiceRef" Loaded="UserControl_Loaded">
<UserControl.Resources>
<CollectionViewSource x:Key="customerViewSource" d:DesignSource="{d:DesignInstance my:Customer, CreateList=True}" />
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<sdk:DataGrid AutoGenerateColumns="False" Height="426" HorizontalAlignment="Left" ItemsSource="{Binding}" Margin="12,12,0,0" Name="customerDataGrid" RowDetailsVisibilityMode="VisibleWhenSelected" VerticalAlignment="Top" Width="776">
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn x:Name="addressColumn" Binding="{Binding Path=Address}" Header="Address" Width="SizeToHeader" />
<sdk:DataGridTextColumn x:Name="cityColumn" Binding="{Binding Path=City}" Header="City" Width="SizeToHeader" />
<sdk:DataGridTextColumn x:Name="companyNameColumn" Binding="{Binding Path=CompanyName}" Header="Company Name" Width="SizeToHeader" />
<sdk:DataGridTextColumn x:Name="contactNameColumn" Binding="{Binding Path=ContactName}" Header="Contact Name" Width="SizeToHeader" />
<sdk:DataGridTextColumn x:Name="contactTitleColumn" Binding="{Binding Path=ContactTitle}" Header="Contact Title" Width="SizeToHeader" />
<sdk:DataGridTextColumn x:Name="countryColumn" Binding="{Binding Path=Country}" Header="Country" Width="SizeToHeader" />
<sdk:DataGridTextColumn x:Name="customerIDColumn" Binding="{Binding Path=CustomerID}" Header="Customer ID" Width="SizeToHeader" />
<sdk:DataGridTextColumn x:Name="faxColumn" Binding="{Binding Path=Fax}" Header="Fax" Width="SizeToHeader" />
<sdk:DataGridTextColumn x:Name="phoneColumn" Binding="{Binding Path=Phone}" Header="Phone" Width="SizeToHeader" />
<sdk:DataGridTextColumn x:Name="postalCodeColumn" Binding="{Binding Path=PostalCode}" Header="Postal Code" Width="SizeToHeader" />
<sdk:DataGridTextColumn x:Name="regionColumn" Binding="{Binding Path=Region}" Header="Region" Width="SizeToHeader" />
</sdk:DataGrid.Columns>
</sdk:DataGrid>
</Grid>
</UserControl>
This is my MainPage.xaml.cs :-
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using SilverlightPlainWCF.CustomersServiceRef;
using System.Diagnostics;
using System.Collections.ObjectModel;
using System.ComponentModel;
namespace SilverlightPlainWCF
{
public partial class MainPage : UserControl, INotifyPropertyChanged
{
public MainPage()
{
InitializeComponent();
this.DataContext = Customers;
this.Loaded += new RoutedEventHandler(MainPage_Loaded);
}
public ObservableCollection<Customer> customers;
public ObservableCollection<Customer> Customers
{
get { return customers; }
set
{
customers = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Customers"));
}
}
}
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
CustomersServiceClient objCustomersServiceClient = new CustomersServiceClient();
objCustomersServiceClient.GetAllCustomersCompleted += (s, res) =>
{
if (res.Error == null)
{
Customers = new ObservableCollection<Customer>(res.Result);
}
else
{
MessageBox.Show(res.Error.Message);
}
};
objCustomersServiceClient.GetAllCustomersAsync();
}
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["Resource Key for CollectionViewSource"];
// myCollectionViewSource.Source = your data
// }
// 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["Resource Key for CollectionViewSource"];
// myCollectionViewSource.Source = your data
// }
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
If i just move the line :-
this.DataContext = Customers;
from constructor to here :-
if (res.Error == null)
{
Customers = new ObservableCollection<Customer>(res.Result);
this.DataContext = Customers;
}
It works fine and I get all the data. What might be the problem?

The reason that it didn't work when you put it in the constructor is that there is not yet any value in the customers field at that moment.
You will only get the value when MainPage_Loaded is triggered, which will not happen because of the following line in your XAML:
Loaded="UserControl_Loaded"
That will execute UserControl_Loaded and not MainPage_Loaded. What you can do is call MainPage_Loaded from UserControl_Loaded, which probably is not what you intend to do. So in that case you should change your XAML instead to:
Loaded="MainPage_Loaded"
And you can delete UserControl_Loaded altogether since you are not using it anymore.
And as for the assigning of the result to the DataGrid, you can actually do it directly by assigning the result straight to the DataContext instead of going through the Customers property.
But if you insist to assign it to the Customers property and have the DataGrid updated accordingly, then the next easiest solution would be to include the following line somewhere in your Customers set method:
DataContext = value;
If you really, really insist that the DataGrid should update itself when the PropertyChanged event is triggered, without having you to code the DataContext = Customers row, then what you want is data binding. By binding the DataContext property to your Customers property, then the DataGrid will be updated when it receive the PropertyChanged event.
To declare the data binding in XAML, you would need to assign a name to your UserControl tag. Then you would assign the binding to the DataContext, something along this line:
DataContext="{Binding Path=Customers, ElementName=theUserControlName}"
And if I were you, instead of having to implement the INotifyPropertyChanged interface, I would instead use Dependency Properties instead. Converting your example to use Dependency Property, I would have:
public static DependencyProperty CustomersProperty =
DependencyProperty.Register("Customers", typeof(ObservableCollection<Customer>), typeof(MainPage), null);
public ObservableCollection<Customer> Customers
{
get { return (ObservableCollection<Customer>) GetValue(CustomersProperty); }
set { SetValue(CustomersProperty, value); }
}
Just that, the property change notification will be handled by the framework.

I believe the problem is that in the constructor you do not have this line:
Customers = new ObservableCollection<Customer>(res.Result);
before you attempt to set the DataContext to that value.

Related

How to get access to text from all the textboxes( where textboxes are created dynamically) in windows phone runtime

I have been trying to get texts from the collection of textboxes which are created dynamically by binding a collection to a stackpanel using items control which is in seperate user control which i am loading on a page in windows phone runtime.
Below is the code of my UserControl:
<UserControl
x:Class="CfMobility.UserControls.CredentialsUserControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:CfMobility.UserControls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<ScrollViewer>
<ItemsControl ItemsSource="{Binding SelectedCategorySettings}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel IsTapEnabled="False">
<TextBlock Text="{Binding SettingKey}" Style="{ThemeResource BaseTextBlockStyle}"></TextBlock>
<TextBox Text="{Binding SettingValue}" Width="300px"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
</UserControl>
I have a Content control in another page as below:
<ContentControl x:Name="Container" Grid.Row="1" Margin="19,10,19,0">
</ContentControl>
Where i am binding this content control to above stackpanel when i am navigating to the page.
As You can see i had bonded "SelectedCategorySettings" collection to StackPanel using ItemsScroll which displays number of text boxes based on the collecion. Here i am unable to figure out if i want to save text from all the text boxes which are displayed on the page into a json file, how to access the text of all the text boxes which are dynamically displayed in above scenario?
PS: note that items is control is in a separate user control.
Thanks in Advance
You should use ObservableCollection for SelectedCategorySettings and your model class which contains SettingKey and SettingValue should implement INotifyPropertyChanged interface as in following example code. If you do it correctly then whatever the changes happen in UI (in your case, text changes of textbox) will automatically reflect in your model objects in the ObservableCollection. If you are interested to learn more about how this works, I recommend you to search about mvvm design pattern in Windows Phone development.
public class Setting : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _settingKey;
public string SettingKey
{
get { return _settingKey; }
set {
_settingKey = value;
OnPropertyChanged("SettingKey");
}
}
private string _settingValue;
public string SettingValue
{
get { return _settingValue; }
set {
_settingValue = value;
OnPropertyChanged("SettingValue");
}
}
public virtual void OnPropertyChanged(string propertyName)
{
var propertyChanged = PropertyChanged;
if (propertyChanged != null)
{
propertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
What you need is a method like this:
var textBoxes = AllTextBoxes(this);
public List<TextBox> AllTextBoxes(DependencyObject parent)
{
var list = new List<TextBox>();
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
if (child is TextBox)
{
list.Add(child as Control);
continue;
}
list.AddRange(AllChildren(child));
}
return list;
}

Xaml two way binding of textbox to observable collection

In my WP8 app I have a class, which has a ObservableCollection<ObservableCollection<int>> property called Matrix.
I want to display these matrices using items control.
<ItemsControl ItemsSource="{Binding FirstMatrix.Matrix}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"></StackPanel>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
The code works as far as displaying is concerned (it's filled with zeros which is a default value). But I also want to allow changes in TextBoxes which would be reflected in Matrix property - now the TextBoxes can't be changed, because their value is bound one way to Matrix cells I guess. I tried setting <TextBox Text="{Binding Mode=TwoWay}" />or sth similar but it doesn't seem to work.
Any ideas how should the data be bound ?
EDIT:
I have implemented the INotifyPropertyChanged.
Here is a part of my class:
public partial class CalcMatrix : INotifyPropertyChanged
{
public ObservableCollection<ObservableCollection<int>> Matrix
{
get { return _matrix; }
set
{
_matrix = value;
OnPropertyChanged("Matrix");
}
}
private ObservableCollection<ObservableCollection<int>> _matrix;
private void OnPropertyChanged(string argName)
{
var handler = PropertyChanged;
if(handler != null)
handler(this, new PropertyChangedEventArgs(argName));
}
public event PropertyChangedEventHandler PropertyChanged;
}
I think the reason the TexBoxes don't change is because the binding is one-way - the Text is always what is inside the Matrix. I believe that i should somehow change the XAML binding to TwoWay or something but don't know how. Any ideas ?
Two way mode binding require path (why? see this SO answer), so you can't do it just like {Binding Mode=TwoWay}, it has to be something like {Binding SomePath, Mode=TwoWay}. Therefore, in this case you have to wrap matrix item to be some class instead of plain int and put that int as property's value of that class.
//your Matrix property type become:
...
public ObservableCollection<ObservableCollection<MatrixElement>> Matrix
...
//MatrixElement class is something like:
public class MatrixElement : INotifyPropertyChanged
{
private int _value;
public int Value
{
get { return _value; }
set {
_value = value;
OnPropertyChanged("Value");
}
}
....
}
//then you can bind TextBox in two way mode
...
<ItemsControl.ItemTemplate>
<DataTemplate>
<TextBox Text="{Binding Value, Mode=TwoWay}" />
</DataTemplate>
</ItemsControl.ItemTemplate>
...
The reason it didnt work is that the itemsource is a list of Matrix and you are not making any changes to the list iteself like adding or removing from a list instead you are changing a property of the item present in list I assume you are using an ObservableCollection....
So you need to implement a INotifyPropertyChanged interface to tell the UI that Hey I am changed please update yourself....
class YourClass : INotifyPropertyChanged
{
private string yourProperty;
public string YourPropety{
get{
return yourProperty;
}
set{
if (value != this.yourProperty)
{
this.yourProperty = value;
NotifyPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}

Windows 8.1: Behaviors on Flyouts don't Work

I am developing a windows 8.1 app using VS 2013 and MVVM Light.
The following code shows the behavior in a flyout within an appbar:
<AppBarButton.Flyout>
<Flyout x:Name="FlyoutCalculator"
Placement="Top"
FlyoutPresenterStyle="{StaticResource FlyoutPresenterBaseStyle}">
<uc:Calculator ApplyCommand="{Binding CancelCommand}"
CancelCommand="{Binding CancelCommand}"
Available="{Binding AvailableCounter, Mode=OneWay}"
SelectedItem="{Binding SelectedItem, Mode=TwoWay}"/>
<interactivity:Interaction.Behaviors>
<core:EventTriggerBehavior EventName="Opening">
<core:InvokeCommandAction Command="{Binding ShowCurrentCostsCommand}" />
</core:EventTriggerBehavior>
</interactivity:Interaction.Behaviors>
</Flyout>
</AppBarButton.Flyout>
Unfortunately I get an exception while compiling the app:
WinRT-Informationen: Cannot add instance of type Microsoft.Xaml.Interactions.Core.EventTriggerBehavior to a collection of type Microsoft.Xaml.Interactivity.BehaviorCollection
Other Behaviors in the View do work, does someone know a solution to this?
Extremely late answer here, but I had the same issue and came up with a solution after finding this post.
I just created a custom behavior specifically for flyouts, used like this. OpenActions will execute when the flyout is opened, and CloseActions will execute when the flyout closes. In this case, I wanted the bottom app bar to not be visible when the flyout was open.
<Flyout Placement="Full">
<i:Interaction.Behaviors>
<behaviors:FlyoutBehavior>
<behaviors:FlyoutBehavior.OpenActions>
<core:ChangePropertyAction PropertyName="Visibility" Value="Collapsed" TargetObject="{Binding ElementName=CommandBar}" />
</behaviors:FlyoutBehavior.OpenActions>
<behaviors:FlyoutBehavior.CloseActions>
<core:ChangePropertyAction PropertyName="Visibility" Value="Visible" TargetObject="{Binding ElementName=CommandBar}" />
</behaviors:FlyoutBehavior.CloseActions>
</behaviors:FlyoutBehavior>
</i:Interaction.Behaviors>
<Grid>
...
</Grid>
</Flyout>
Code is here:
class FlyoutBehavior : DependencyObject, IBehavior
{
public DependencyObject AssociatedObject { get; private set; }
public void Attach(Windows.UI.Xaml.DependencyObject associatedObject)
{
var flyout = associatedObject as FlyoutBase;
if (flyout == null)
throw new ArgumentException("FlyoutBehavior can be attached only to FlyoutBase");
AssociatedObject = associatedObject;
flyout.Opened += FlyoutOpened;
flyout.Closed += FlyoutClosed;
}
public void Detach()
{
var flyout = AssociatedObject as FlyoutBase;
if (flyout != null)
{
flyout.Opened -= FlyoutOpened;
flyout.Closed -= FlyoutClosed;
}
}
public static readonly DependencyProperty OpenActionsProperty =
DependencyProperty.Register("OpenActions", typeof(ActionCollection), typeof(FlyoutBehavior), new PropertyMetadata(null));
public ActionCollection OpenActions
{
get { return GetValue(OpenActionsProperty) as ActionCollection; }
set { SetValue(OpenActionsProperty, value); }
}
public static readonly DependencyProperty CloseActionsProperty =
DependencyProperty.Register("CloseActions", typeof(ActionCollection), typeof(FlyoutBehavior), new PropertyMetadata(null));
public ActionCollection CloseActions
{
get { return GetValue(CloseActionsProperty) as ActionCollection; }
set { SetValue(CloseActionsProperty, value); }
}
private void FlyoutOpened(object sender, object e)
{
foreach (IAction action in OpenActions)
{
action.Execute(AssociatedObject, null);
}
}
private void FlyoutClosed(object sender, object e)
{
foreach (IAction action in CloseActions)
{
action.Execute(AssociatedObject, null);
}
}
public FlyoutBehavior()
{
OpenActions = new ActionCollection();
CloseActions = new ActionCollection();
}
}
I do not have a solution but:
I'm not using Flyouts in my Windows 8.1 App, I'm using a UserControl on which I have added a EventTriggerBehavior as you did. And I get exactly the same Errormessage from VisualStudio at runtime.
As I am using a RoutedEventHandler this could cause the Problem as you use
EventHandler<object> Opening
as the Trigger for the Behavior. But that is just an idea of what is the problem.
For me I have found an answer:
I have changed the Type of my RoutedEventHandler to be just a normal EventHandler. And the Method inside the CodeBehind which triggers the RoutedEventHandler is invoked with only the sender, because I dont know how to convert RoutedEventArgs into EventArgs, but as long as I dont need the EventArgs it's not a problem.
You could also make a workaround by creating a UserControl with a Flyout Control and make the Opening Event public to the Page where you use it. Then you can add the EventTriggerBehavior to the UserControl and connect it to your custom Opening Event and you should get the expected behavior.

Binding to Xaml

I am binding a model to my Xaml code and have a question about how to bind to a Property.
Let's assume my View Model looks like
internal class LogsVM
{
private List<Log> logList;
public List<Log> LogList
{
get; set;
}
public LogsVM()
{
}
public LogsVM(List<Logging.Log> logs)
{
logList = logs;
}
}
and assume my Log class looks like
internal class Log
{
public string Title { get;set; }
public List<MoreDetails> moreDetails;
public Log()
{
moreDetails= new List<MoreDetails>();
}
}
In Xaml, how do I bind to the Title within a TreeView?
My Xaml so far looks like
<Window x:Class="BackUps.Logging.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:myData ="clr-namespace:BackUps.Logging.ViewModel"
Title="Logging Results" Height="350" Width="525">
<Grid>
<Grid.Resources>
<myData:LogsVM x:Key="Vm" />
</Grid.Resources>
<Grid.DataContext>
<Binding Source="{StaticResource Vm}"></Binding>
</Grid.DataContext>
<TreeView>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type myData:LogsVM}" ItemsSource="{Binding LogList}">
<TextBlock Text="{Binding Title}" />
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate DataType="{x:Type myData:LogsVM}">
<TextBlock Text="{Binding moreDetails.Staus}" />
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</Grid>
</Window>
And my MainWindow code behind
public MainWindow(List<Log> logs)
{
InitializeComponent();
LogsVM logVm = new LogsVM(logs);
this.DataContext = logVm;
}
As you can see in the above code, I'm trying to bind the Title property but my screen doesn't display an text at all.
So, my 2 questions are:
Is it enough to use my ViewModel class alone or do I also need to tell the Xaml each internal class of the ViewModel (in this case, the Log class)? EG
xmlns:myData ="clr-namespace:BackUps.Logging.ViewModel"
xmlns:moreData = "clr-namespace:BackUps.Logging.Logs"
What do I need to do to bind the Title?
Binding is not complicated as you might think, Your are just not mastering the Treeview's HierarchicalDataTemplate stuff and exposing properties to the XAML,
set your all your domain classes public cause they are used in public properties.
myData should reference the domain classes namespace.for ex: in my case xmlns:myData="clr-namespace:WpfApplication3" MoreDetails has to be a public property in Log class.
<TreeView ItemsSource="{Binding LogList}" >
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type myData:Log}" ItemsSource="{Binding MoreDetails}">
<TextBlock Text="{Binding Title}" />
<HierarchicalDataTemplate.ItemTemplate >
<DataTemplate DataType="{x:Type myData:MoreDetails}" >
<TextBlock Text="{Binding Status}" />
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
public class Log
{
public string Title { get; set; }
public List<MoreDetails> MoreDetails { get; set; }
public Log()
{
MoreDetails = new List<MoreDetails>();
}
}
public class MoreDetails
{
public string Status { get; set; }
}
public class YourVM
{
public YourVM() // in my case i've just run it fast in code behind
{
LogList = new List<Log>
{
new Log{Title = "Hichem", MoreDetails = new List<MoreDetails>{ new MoreDetails{Status = "OK"}}},
new Log{Title = "Hichem"},
new Log{Title = "Hichem"},
new Log{Title = "Hichem"},
};
}
public List<Log> LogList { get; set; }
}

Refresh DataGrid MVVM Silverlight

I have got a Silverlight Page which contains a DataGrid .It is bound to a ViewModel.On the initialization of the ViewModel I have called a RIA Services to fetch all records from database.I have another button on the page which opens a child form on click.This child form contains DataForm which adds a record to the database and after successfully adding the record again I fetched all the record using RIA Services and RaisedPropertyChanged event.But the DataGrid does not shows the new record.What is the problem and why the DataGrid is not getting refreshed...The code of view and viewmodel is written below.
//XAML of View
<sdk:DataGrid x:Name="grd_classes" ItemsSource="{Binding Classes,Mode=TwoWay}" AutoGenerateColumns="False" Width="300" Grid.Column="1" >
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn Header="Class Name" Width="140" Binding="{Binding Name,Mode=TwoWay}" CanUserReorder="True" CanUserResize="True" CanUserSort="True" />
<sdk:DataGridTextColumn Header="Alias" Width="140" Binding="{Binding Alias,Mode=TwoWay}" CanUserReorder="True" CanUserResize="True" CanUserSort="True" />
</sdk:DataGrid.Columns>
</sdk:DataGrid>
//Code of viewmodel
namespace SMS.ViewModel
{
public class ClassesViewModel:ViewModel
{
private ClassesContext _context = new ClassesContext();
public ClassesViewModel()
{
_context.Load<Class>(_context.GetClassesQuery(), OnLoad, true);
}
public EntitySet<Class> Classes
{
get
{
return _context.Classes;
}
}
public void AddNewClass(object parameter)
{
for (int i = 0; i <= newClass.Count - 1;i++ )
{
_context.Classes.Add(newClass[i]);
}
_context.SubmitChanges(OnSave,null);
}
private void OnLoad(LoadOperation op)
{
if (!op.HasError)
{
RaisePropertyChanged("Classes");
}
}
private void OnSave(SubmitOperation op)
{
if (op.IsComplete)
{
if (op.HasError)
{
MessageBox.Show("Error");
}
else
{
_context = new ClassesContext();
_context.Load<Class>(_context.GetClassesQuery(), OnLoad, true);
DialogResult = true;
}
}
}
}
}
have you set grd_classes DataContext ? also need RaisePropertychanged event as well
_context.Load<Class>(_context.GetClassesQuery(), OnLoad, true);
RaisePropertyChanged(() => Classes);