How to use MVVM Light With Sql Server Compact - Windows Phone 7? - c#

I am using MVVM Light, Sql Server Compact Toolkit and windows phone 7.
I created a sql server compact 3.5 database and then used the toolkit to generate the datacontext and domain class for each table.
Looks like this
[global::System.Data.Linq.Mapping.TableAttribute(Name = "ContactGroups")]
public partial class ContactGroup : INotifyPropertyChanging, INotifyPropertyChanged
{
private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);
private int _Id;
private string _Title;
private System.DateTime _LastUpdated;
private EntitySet<GContact> _GContacts;
#region Extensibility Method Definitions
partial void OnLoaded();
partial void OnValidate(System.Data.Linq.ChangeAction action);
partial void OnCreated();
partial void OnIdChanging(int value);
partial void OnIdChanged();
partial void OnTitleChanging(string value);
partial void OnTitleChanged();
partial void OnLastUpdatedChanging(System.DateTime value);
partial void OnLastUpdatedChanged();
#endregion
public ContactGroup()
{
this._GContacts = new EntitySet<GContact>(new Action<GContact>(this.attach_GContacts), new Action<GContact>(this.detach_GContacts));
OnCreated();
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage = "_Id", DbType = "Int NOT NULL", IsPrimaryKey = true)]
public int Id
{
get
{
return this._Id;
}
set
{
if ((this._Id != value))
{
this.OnIdChanging(value);
this.SendPropertyChanging();
this._Id = value;
this.SendPropertyChanged("Id");
this.OnIdChanged();
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage = "_Title", DbType = "NVarChar(100) NOT NULL", CanBeNull = false)]
public string Title
{
get
{
return this._Title;
}
set
{
if ((this._Title != value))
{
this.OnTitleChanging(value);
this.SendPropertyChanging();
this._Title = value;
this.SendPropertyChanged("Title");
this.OnTitleChanged();
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage = "_LastUpdated", DbType = "DateTime NOT NULL")]
public System.DateTime LastUpdated
{
get
{
return this._LastUpdated;
}
set
{
if ((this._LastUpdated != value))
{
this.OnLastUpdatedChanging(value);
this.SendPropertyChanging();
this._LastUpdated = value;
this.SendPropertyChanged("LastUpdated");
this.OnLastUpdatedChanged();
}
}
}
[global::System.Data.Linq.Mapping.AssociationAttribute(Name = "FK_GContacts_ContactGroups", Storage = "_GContacts", ThisKey = "Id", OtherKey = "ContactGroups_Id", DeleteRule = "NO ACTION")]
public EntitySet<GContact> GContacts
{
get
{
return this._GContacts;
}
set
{
this._GContacts.Assign(value);
}
}
public event PropertyChangingEventHandler PropertyChanging;
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void SendPropertyChanging()
{
if ((this.PropertyChanging != null))
{
this.PropertyChanging(this, emptyChangingEventArgs);
}
}
protected virtual void SendPropertyChanged(String propertyName)
{
if ((this.PropertyChanged != null))
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private void attach_GContacts(GContact entity)
{
this.SendPropertyChanging();
entity.ContactGroup = this;
}
private void detach_GContacts(GContact entity)
{
this.SendPropertyChanging();
entity.ContactGroup = null;
}
}
Yet when I try to make it blendable(ie make fake data so when I go into blend I can work with it better instead of looking at empty boxes) nothing shows up in blend
when I have a simple domain without it works
public class ContactGroup
{
public int Id { get; set; }
public string Title { get; set; }
public DateTime LastUpdated { get; set; }
public List<GContacts> Contacts { get; set; }
public ContactGroup()
{
Contacts = new List<GContacts>();
}
}
Then in my viewmodel locator I would have
if (ViewModelBase.IsInDesignModeStatic)
{
SimpleIoc.Default.Register<IContactService, DesignContactService>();
}
else
{
SimpleIoc.Default.Register<IContactService, DesignContactService>();
}
Edit
The problem line seens to be this
private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);
When I remove it then blend shows the data again.

Related

Serialize object in WPF to XML

So I'm building an application in WPF using MVVM and I want to save various object model data as XML. Using Serialize an object to XML I can correctly serialize objects to XML, but the issue I'm having is with the MVVM itself.
I can't directly access the Model of the object within the ICommand segments of the ViewModel code (E.G. When I hit save, that goes to an ICommand method inside the ViewModel).
I've made the Model is question serializable, I just have no way to pass it directly to my Serialize method (which is contained in it's own static Helper class) so even if I weren't getting "Unexpected type" spit back at me (since VieWModel is not serializable) I'd end up with a lot of excess garbage, not just the Model class being serialized.
I'm not sure if I'm just designing this incorrectly, or if there's a better way to do it or...?
P.S. All of these fields are just being written into TextBox controls that are bound appropriately. Right now I'm only trying to do the name fields to avoid any kind of issues with other data types not working right.
EDIT: As requested in a comment, the goal right now is just to be able to write some bits of text in a few text boxes (First, middle, last names), then save that to an XML file.
Summarized Model in question:
namespace XMLaw.Model
{
[Serializable]
public class ClientModel
{
private string firstName { get; set; }
private string middleName { get; set; }
private string lastName { get; set; }
private DateTime dateOfBirth { get; set; }
private string ssn { get; set; } //Format: AA ## ## ## A, spaces optional
private string address { get; set; }
private string phone { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#region Name Properties
public string FirstName
{
get { return firstName; }
set
{
if( firstName != value )
{
firstName = value;
OnPropertyChanged("FirstName");
}
}
}
public string MiddleName
{
get { return middleName; }
set
{
if (middleName != value)
{
middleName = value;
OnPropertyChanged("MiddleName");
}
}
}
public string LastName
{
get { return lastName; }
set
{
if (lastName != value)
{
lastName = value;
OnPropertyChanged("LastName");
}
}
}
#endregion
public DateTime DateOfBirth
{
get { return dateOfBirth; }
set
{
if ( dateOfBirth != value )
{
DateTime dt = Convert.ToDateTime(value); //This will probably need to revisited since DateTime objects are fucking stupid
dateOfBirth = dt.Date;
OnPropertyChanged("DateOfBirth");
}
}
}
public string SSN
{
get { return ssn; }
set
{
if( ssn != value)
{
ssn = value;
OnPropertyChanged("SSN");
}
}
}
public string Address
{
get { return address; }
set
{
if( address != value)
{
address = value;
OnPropertyChanged("Address");
}
}
}
public string Phone
{
get { return phone; }
set
{
if( phone != value )
{
phone = value;
OnPropertyChanged("Phone");
}
}
}
}
}
And the ViewModel in question (The Save command that calls the serialization is at the bottom)
namespace XMLaw.ViewModel
{
public class ClientViewModel : INotifyPropertyChanged
{
private ClientModel client;
private string displayMessage;
private ICommand btnSave;
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public ClientViewModel()
{
client = new ClientModel();
}
public ClientModel ClientModel
{
get { return client; }
}
public string DisplayMessage
{
get { return displayMessage; }
set
{
if( displayMessage != value)
{
displayMessage = value;
OnPropertyChanged("DisplayMessage");
}
}
}
public ICommand SaveCommand
{
get
{
if (btnSave == null)
btnSave = new Save();
return btnSave;
}
set { btnSave = value; }
}
protected class Save : ICommand
{
public bool CanExecute(object param) { return true; }
public event EventHandler CanExecuteChanged; //Compiler yells at you if you don't implement this from inhereted ICommand
public void Execute(object param)
{
ClientViewModel viewModel = (ClientViewModel)param;
//TODO: Insert XML serialization and save to a file
var xml = Helper.Serialize(param);
//Placeholder to make sure the button works
viewModel.DisplayMessage = "You clicked the button at " + DateTime.Now;
}
}
}
}
And the Serailization method I shamelessly took from the above link
public static class Helper
{
public static string Serialize<T>(this T value)
{
if (value == null)
{
return string.Empty;
}
try
{
var xmlserializer = new XmlSerializer(typeof(T));
var stringWriter = new StringWriter();
using (var writer = XmlWriter.Create(stringWriter))
{
xmlserializer.Serialize(writer, value);
return stringWriter.ToString();
}
}
catch (Exception ex)
{
throw new Exception("An error occurred", ex);
}
}
}
Change your Client-Model to this:
[Serializable]
public class ClientModel
{
private string firstName;
private string middleName;
private string lastName;
private DateTime dateOfBirth;
private string ssn;
private string address;
private string phone;
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
#region Name Properties
public string FirstName {
get { return firstName; }
set {
if (firstName != value)
{
firstName = value;
OnPropertyChanged("FirstName");
}
}
}
public string MiddleName {
get { return middleName; }
set {
if (middleName != value)
{
middleName = value;
OnPropertyChanged("MiddleName");
}
}
}
public string LastName {
get { return lastName; }
set {
if (lastName != value)
{
lastName = value;
OnPropertyChanged("LastName");
}
}
}
#endregion
public DateTime DateOfBirth {
get { return dateOfBirth; }
set {
if (dateOfBirth != value)
{
DateTime dt = Convert.ToDateTime(value); //This will probably need to revisited since DateTime objects are fucking stupid
dateOfBirth = dt.Date;
OnPropertyChanged("DateOfBirth");
}
}
}
public string SSN {
get { return ssn; }
set {
if (ssn != value)
{
ssn = value;
OnPropertyChanged("SSN");
}
}
}
public string Address {
get { return address; }
set {
if (address != value)
{
address = value;
OnPropertyChanged("Address");
}
}
}
public string Phone {
get { return phone; }
set {
if (phone != value)
{
phone = value;
OnPropertyChanged("Phone");
}
}
}
}
Usage:
var xx = new ClientModel();
xx.FirstName = "John";
xx.LastName = "Smith";
xx.DateOfBirth = DateTime.Now;
var result = xx.Serialize();
Result:
http://www.w3.org/2001/XMLSchema-instance\"
xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\">
John Smith
2016-07-11T00:00:00+02:00
EDIT:
This code:
public void Execute(object param)
{
ClientViewModel viewModel = (ClientViewModel)param;
//TODO: Insert XML serialization and save to a file
var xml = Helper.Serialize(param);
//Placeholder to make sure the button works
viewModel.DisplayMessage = "You clicked the button at " + DateTime.Now;
}
Should be replaced by this:
public void Execute(object param)
{
ClientModel model= (ClientModel )param;
//TODO: Insert XML serialization and save to a file
var xml = Helper.Serialize(param);
//Placeholder to make sure the button works
viewModel.DisplayMessage = "You clicked the button at " + DateTime.Now;
}
Make sure, your Param is of type ClientModel.
I also highly recommend you, to get into the basics of how DataBinding works
Edit 2 (The Command-Thingy):
class Save : ICommand
{
public ClientModel Model { get; set; }
public bool CanExecute(object param) { return true; }
public event EventHandler CanExecuteChanged; //Compiler yells at you if you don't implement this from inhereted ICommand
public void Execute(object param)
{
//TODO: Insert XML serialization and save to a file
var xml = Helper.Serialize(this.Model);
//Placeholder to make sure the button works
viewModel.DisplayMessage = "You clicked the button at " + DateTime.Now;
}
}
Usage:
public ICommand SaveCommand
{
get
{
if (btnSave == null)
btnSave = new Save();
btnSave.Model = this.ClientModel;
return btnSave;
}
set { btnSave = value; }
}

A first chance exception of type 'System.Data.SqlServerCe.SqlCeException' occurred in Microsoft.Phone.Data.Internal.ni.dll

I have added a new column to my database table. When I have added this new columnm, the first chance exception start appearing. When I debugged it, it stated the code line
MLongListSelector.ItemsSource = c.ToDoList.ToList();
is the next statement to execute that causes the problem. What have I done wrong there?
using (DatabaseContext c = new DatabaseContext(DatabaseContext.ConnectionString))
{
c.CreateIfNotExists();
c.LogDebug = true;
//output todolist data from database
MLongListSelector.ItemsSource = c.ToDoList.ToList();
}
stack trace of that line:
ex.StackTrace " at System.Data.SqlServerCe.SqlCeCommand.ProcessResults(Int32 hr)\r\n at System.Data.SqlServerCe.SqlCeCommand.CompileQueryPlan()\r\n at System.Data.SqlServerCe.SqlCeCommand.ExecuteCommand(CommandBehavior behavior, String method, ResultSetOptions options)\r\n at System.Data.SqlServerCe.SqlCeCommand.ExecuteDbDataReader(CommandBehavior behavior)\r\n at System.Data.Linq.SqlClient.SqlProvider.Execute(Expression query, QueryInfo queryInfo, IObjectReaderFactory factory, Object[] parentArgs, Object[] userArgs, ICompiledSubQuery[] subQueries, Object lastResult, Boolean isCompiledQuery)\r\n at System.Data.Linq.SqlClient.SqlProvider.ExecuteAll(Expression query, QueryInfo[] queryInfos, IObjectReaderFactory factory, Object[] userArguments, ICompiledSubQuery[] subQueries, Boolean isCompiledQuery)\r\n at System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query)\r\n at System.Data.Linq.Table`1.GetEnumerator()\r\n at System.Data.Linq.Table`1.System.Collections.Generic.IEnumerable<TEntity>.GetEnumerator()\r\n at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)\r\n at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)\r\n at PhoneApp.MainPage.OnNavigatedTo(NavigationEventArgs e)"
e.message:
ex.Message "The column name is not valid. [ Node name (if any) = t0,Column name = Col ]" string
Get and Set:
public partial class ToDoList : INotifyPropertyChanging, INotifyPropertyChanged
{
private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);
private int _Id;
private string _Title;
private string _Description;
private string _Col;
#region Extensibility Method Definitions
partial void OnLoaded();
partial void OnValidate(System.Data.Linq.ChangeAction action);
partial void OnCreated();
partial void OnIdChanging(int value);
partial void OnIdChanged();
partial void OnTitleChanging(string value);
partial void OnTitleChanged();
partial void OnDescriptionChanging(string value);
partial void OnDescriptionChanged();
partial void OnColChanging(string value);
partial void OnColChanged();
#endregion
public ToDoList()
{
OnCreated();
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_Id", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)]
public int Id
{
get
{
return this._Id;
}
set
{
if ((this._Id != value))
{
this.OnIdChanging(value);
this.SendPropertyChanging();
this._Id = value;
this.SendPropertyChanged("Id");
this.OnIdChanged();
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_Title", DbType="NVarChar(100) NOT NULL", CanBeNull=false)]
public string Title
{
get
{
return this._Title;
}
set
{
if ((this._Title != value))
{
this.OnTitleChanging(value);
this.SendPropertyChanging();
this._Title = value;
this.SendPropertyChanged("Title");
this.OnTitleChanged();
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_Description", DbType="NVarChar(100)")]
public string Description
{
get
{
return this._Description;
}
set
{
if ((this._Description != value))
{
this.OnDescriptionChanging(value);
this.SendPropertyChanging();
this._Description = value;
this.SendPropertyChanged("Description");
this.OnDescriptionChanged();
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage="_Col", DbType="NVarChar(25)")]
public string Col
{
get
{
return this._Col;
}
set
{
if ((this._Col != value))
{
this.OnColChanging(value);
this.SendPropertyChanging();
this._Col = value;
this.SendPropertyChanged("Col");
this.OnColChanged();
}
}
}
public event PropertyChangingEventHandler PropertyChanging;
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void SendPropertyChanging()
{
if ((this.PropertyChanging != null))
{
this.PropertyChanging(this, emptyChangingEventArgs);
}
}
protected virtual void SendPropertyChanged(String propertyName)
{
if ((this.PropertyChanged != null))
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
I just tried your solution and i don't see why it should not work. Do you have the ToDoList marked with a "Table attribute"? i.e.
[Table]
public partial class ToDoList : INotifyPropertyChanging, INotifyPropertyChanged
Also, it might be worth you dropping the database and recreating it. Follow the code sample below and try to go from there. if this does not work then feel free to attach a simple project that replicates the issue.
Xaml
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<ListBox x:Name="lstToDos">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Title}"></TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
Code behind
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
using (DatabaseContext c = new DatabaseContext(DatabaseContext.ConnectionString))
{
c.CreateIfNotExists();
//Add new records for debug sake:
var dateNow = DateTime.UtcNow.TimeOfDay.ToString();
var newToDo = new ToDoList { Col = "Col" + dateNow, Description = "Some description" + dateNow, Title = "Some title" + dateNow };
c.ToDoLists.InsertOnSubmit(newToDo);
c.SubmitChanges();
lstToDos.ItemsSource = c.ToDoLists.ToList();
}
}
}
Data context file
public class DatabaseContext : DataContext
{
public DatabaseContext(string connectionString)
: base(connectionString)
{
}
public Table<ToDoList> ToDoLists
{
get
{
return this.GetTable<ToDoList>();
}
}
public void CreateIfNotExists()
{
if (!this.DatabaseExists())
{
this.CreateDatabase();
}
}
public const string ConnectionString = #"isostore:/MyDatabases.sdf";
}
ToDO entity
[Table]
public partial class ToDoList : INotifyPropertyChanging, INotifyPropertyChanged
{
private static PropertyChangingEventArgs emptyChangingEventArgs = new PropertyChangingEventArgs(String.Empty);
private int _Id;
private string _Title;
private string _Description;
private string _Col;
#region Extensibility Method Definitions
partial void OnLoaded();
partial void OnValidate(System.Data.Linq.ChangeAction action);
partial void OnCreated();
partial void OnIdChanging(int value);
partial void OnIdChanged();
partial void OnTitleChanging(string value);
partial void OnTitleChanged();
partial void OnDescriptionChanging(string value);
partial void OnDescriptionChanged();
partial void OnColChanging(string value);
partial void OnColChanged();
#endregion
public ToDoList()
{
OnCreated();
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage = "_Id", AutoSync = AutoSync.OnInsert, DbType = "Int NOT NULL IDENTITY", IsPrimaryKey = true, IsDbGenerated = true)]
public int Id
{
get
{
return this._Id;
}
set
{
if ((this._Id != value))
{
this.OnIdChanging(value);
this.SendPropertyChanging();
this._Id = value;
this.SendPropertyChanged("Id");
this.OnIdChanged();
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage = "_Title", DbType = "NVarChar(100) NOT NULL", CanBeNull = false)]
public string Title
{
get
{
return this._Title;
}
set
{
if ((this._Title != value))
{
this.OnTitleChanging(value);
this.SendPropertyChanging();
this._Title = value;
this.SendPropertyChanged("Title");
this.OnTitleChanged();
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage = "_Description", DbType = "NVarChar(100)")]
public string Description
{
get
{
return this._Description;
}
set
{
if ((this._Description != value))
{
this.OnDescriptionChanging(value);
this.SendPropertyChanging();
this._Description = value;
this.SendPropertyChanged("Description");
this.OnDescriptionChanged();
}
}
}
[global::System.Data.Linq.Mapping.ColumnAttribute(Storage = "_Col", DbType = "NVarChar(25)")]
public string Col
{
get
{
return this._Col;
}
set
{
if ((this._Col != value))
{
this.OnColChanging(value);
this.SendPropertyChanging();
this._Col = value;
this.SendPropertyChanged("Col");
this.OnColChanged();
}
}
}
public event PropertyChangingEventHandler PropertyChanging;
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void SendPropertyChanging()
{
if ((this.PropertyChanging != null))
{
this.PropertyChanging(this, emptyChangingEventArgs);
}
}
protected virtual void SendPropertyChanged(String propertyName)
{
if ((this.PropertyChanged != null))
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}

the member " ..." has no supported translation to SQL error

im learning the ropes in LINQ and created a DB and been trying to update a table record but i keep getting the member P.roject1.ChildDBdetails.Id has no supported translation to SQL.
this is the query:
public void UpdateChildrecord()
{
using (ChildDBDataContext ChildDB = new ChildDBDataContext(Con_String))
{
IQueryable<ChildDBdetails> query =
from c in ChildDB.ChildDBdetails
where c.Id == id
select c;
ChildDBdetails updaterecord = query.FirstOrDefault();
updaterecord.Team = newteam;
ChildDB.SubmitChanges();
}
}
i'm a newbie to linq-to_sql and don't really understand why this is happening.how can i fix the error?
thanks.
TableModel:
[Table]
public class ChildDBdetails : INotifyPropertyChanged, INotifyPropertyChanging
{
[Column(IsPrimaryKey = true, IsDbGenerated = false, CanBeNull = false)]
private int id;
public int Id
{
get { return id; }
set
{
NotifyPropertyChanging("Id");
id = value;
NotifyPropertyChanged("Id");
}
}
[Column]
private string team;
public string Team
{
get { return team; }
set
{
NotifyPropertyChanging("Team");
team = value;
NotifyPropertyChanged("Team");
}
}
#region Implementation of INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
#region Implementation of INotifyPropertyChanging
public event PropertyChangingEventHandler PropertyChanging;
private void NotifyPropertyChanging(string propertyName)
{
if (PropertyChanging != null)
{
PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
}
}
#endregion
}

Equal is not defined between type Nullable<Int32> and Int32

I am writing a boring application to manage patients and their clinic history. I used SQLite combined with DbLinq libraries and DbMetal code generation utility. Here are two classes from the genereated code extracted from the underlying database:
[Table(Name="main.Patients")]
public partial class Patient : System.ComponentModel.INotifyPropertyChanging, System.ComponentModel.INotifyPropertyChanged
{
private static System.ComponentModel.PropertyChangingEventArgs emptyChangingEventArgs = new System.ComponentModel.PropertyChangingEventArgs("");
private long _birthday;
private string _firstName;
private int _hasChildren;
private System.Nullable<int> _id;
private int _isMarried;
private string _lastName;
private string _profession;
private EntitySet<ClinicCase> _clinicCases;
private EntitySet<PatientAddress> _patientsAddresses;
private EntitySet<PatientPhoneNumber> _patientsPhoneNumbers;
#region Extensibility Method Declarations
partial void OnCreated();
partial void OnBirthdayChanged();
partial void OnBirthdayChanging(long value);
partial void OnFirstNameChanged();
partial void OnFirstNameChanging(string value);
partial void OnHasChildrenChanged();
partial void OnHasChildrenChanging(int value);
partial void OnIDChanged();
partial void OnIDChanging(System.Nullable<int> value);
partial void OnIsMarriedChanged();
partial void OnIsMarriedChanging(int value);
partial void OnLastNameChanged();
partial void OnLastNameChanging(string value);
partial void OnProfessionChanged();
partial void OnProfessionChanging(string value);
#endregion
public Patient()
{
_clinicCases = new EntitySet<ClinicCase>(new Action<ClinicCase>(this.ClinicCases_Attach), new Action<ClinicCase>(this.ClinicCases_Detach));
_patientsAddresses = new EntitySet<PatientAddress>(new Action<PatientAddress>(this.PatientsAddresses_Attach), new Action<PatientAddress>(this.PatientsAddresses_Detach));
_patientsPhoneNumbers = new EntitySet<PatientPhoneNumber>(new Action<PatientPhoneNumber>(this.PatientsPhoneNumbers_Attach), new Action<PatientPhoneNumber>(this.PatientsPhoneNumbers_Detach));
this.OnCreated();
}
[Column(Storage="_birthday", Name="Birthday", DbType="integer", AutoSync=AutoSync.Never, CanBeNull=false)]
[DebuggerNonUserCode()]
public long BirthdayBinaryDate
{
get
{
return this._birthday;
}
set
{
if ((_birthday != value))
{
this.OnBirthdayChanging(value);
this.SendPropertyChanging();
this._birthday = value;
this.SendPropertyChanged("Birthday");
this.OnBirthdayChanged();
}
}
}
[Column(Storage="_firstName", Name="FirstName", DbType="text", AutoSync=AutoSync.Never, CanBeNull=false)]
[DebuggerNonUserCode()]
public string FirstName
{
get
{
return this._firstName;
}
set
{
if (((_firstName == value)
== false))
{
this.OnFirstNameChanging(value);
this.SendPropertyChanging();
this._firstName = value;
this.SendPropertyChanged("FirstName");
this.OnFirstNameChanged();
}
}
}
[Column(Storage="_hasChildren", Name="HasChildren", DbType="integer", AutoSync=AutoSync.Never, CanBeNull=false)]
[DebuggerNonUserCode()]
public int HasChildren
{
get
{
return this._hasChildren;
}
set
{
if ((_hasChildren != value))
{
this.OnHasChildrenChanging(value);
this.SendPropertyChanging();
this._hasChildren = value;
this.SendPropertyChanged("HasChildren");
this.OnHasChildrenChanged();
}
}
}
[Column(Storage="_id", Name="ID", DbType="integer", IsPrimaryKey=true, IsDbGenerated=true, AutoSync=AutoSync.OnInsert)]
[DebuggerNonUserCode()]
public System.Nullable<int> ID
{
get
{
return this._id;
}
set
{
if ((_id != value))
{
this.OnIDChanging(value);
this.SendPropertyChanging();
this._id = value;
this.SendPropertyChanged("ID");
this.OnIDChanged();
}
}
}
[Column(Storage="_isMarried", Name="IsMarried", DbType="integer", AutoSync=AutoSync.Never, CanBeNull=false)]
[DebuggerNonUserCode()]
public int IsMarried
{
get
{
return this._isMarried;
}
set
{
if ((_isMarried != value))
{
this.OnIsMarriedChanging(value);
this.SendPropertyChanging();
this._isMarried = value;
this.SendPropertyChanged("IsMarried");
this.OnIsMarriedChanged();
}
}
}
[Column(Storage="_lastName", Name="LastName", DbType="text", AutoSync=AutoSync.Never, CanBeNull=false)]
[DebuggerNonUserCode()]
public string LastName
{
get
{
return this._lastName;
}
set
{
if (((_lastName == value)
== false))
{
this.OnLastNameChanging(value);
this.SendPropertyChanging();
this._lastName = value;
this.SendPropertyChanged("LastName");
this.OnLastNameChanged();
}
}
}
[Column(Storage="_profession", Name="Profession", DbType="text", AutoSync=AutoSync.Never)]
[DebuggerNonUserCode()]
public string Profession
{
get
{
return this._profession;
}
set
{
if (((_profession == value)
== false))
{
this.OnProfessionChanging(value);
this.SendPropertyChanging();
this._profession = value;
this.SendPropertyChanged("Profession");
this.OnProfessionChanged();
}
}
}
#region Children
[Association(Storage="_clinicCases", OtherKey="PatientID", ThisKey="ID", Name="fk_ClinicCases_0")]
[DebuggerNonUserCode()]
public EntitySet<ClinicCase> ClinicCases
{
get
{
return this._clinicCases;
}
set
{
this._clinicCases = value;
}
}
[Association(Storage="_patientsAddresses", OtherKey="PatientID", ThisKey="ID", Name="fk_PatientsAddresses_0")]
[DebuggerNonUserCode()]
public EntitySet<PatientAddress> Addresses
{
get
{
return this._patientsAddresses;
}
set
{
this._patientsAddresses = value;
}
}
[Association(Storage="_patientsPhoneNumbers", OtherKey="PatientID", ThisKey="ID", Name="fk_PatientsPhoneNumbers_0")]
[DebuggerNonUserCode()]
public EntitySet<PatientPhoneNumber> PhoneNumbers
{
get
{
return this._patientsPhoneNumbers;
}
set
{
this._patientsPhoneNumbers = value;
}
}
#endregion
public event System.ComponentModel.PropertyChangingEventHandler PropertyChanging;
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
protected virtual void SendPropertyChanging()
{
System.ComponentModel.PropertyChangingEventHandler h = this.PropertyChanging;
if ((h != null))
{
h(this, emptyChangingEventArgs);
}
}
protected virtual void SendPropertyChanged(string propertyName)
{
System.ComponentModel.PropertyChangedEventHandler h = this.PropertyChanged;
if ((h != null))
{
h(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
#region Attachment handlers
private void ClinicCases_Attach(ClinicCase entity)
{
this.SendPropertyChanging();
entity.Patient = this;
}
private void ClinicCases_Detach(ClinicCase entity)
{
this.SendPropertyChanging();
entity.Patient = null;
}
private void PatientsAddresses_Attach(PatientAddress entity)
{
this.SendPropertyChanging();
entity.Patient = this;
}
private void PatientsAddresses_Detach(PatientAddress entity)
{
this.SendPropertyChanging();
entity.Patient = null;
}
private void PatientsPhoneNumbers_Attach(PatientPhoneNumber entity)
{
this.SendPropertyChanging();
entity.Patient = this;
}
private void PatientsPhoneNumbers_Detach(PatientPhoneNumber entity)
{
this.SendPropertyChanging();
entity.Patient = null;
}
#endregion
}
[Table(Name="main.PatientsAddresses")]
public partial class PatientAddress : System.ComponentModel.INotifyPropertyChanging, System.ComponentModel.INotifyPropertyChanged
{
private static System.ComponentModel.PropertyChangingEventArgs emptyChangingEventArgs = new System.ComponentModel.PropertyChangingEventArgs("");
private string _address;
private string _domicileStatus;
private System.Nullable<int> _patientID;
private EntityRef<Patient> _patients = new EntityRef<Patient>();
#region Extensibility Method Declarations
partial void OnCreated();
partial void OnAddressChanged();
partial void OnAddressChanging(string value);
partial void OnDomicileStatusChanged();
partial void OnDomicileStatusChanging(string value);
partial void OnPatientIDChanged();
partial void OnPatientIDChanging(System.Nullable<int> value);
#endregion
public PatientAddress()
{
this.OnCreated();
}
[Column(Storage="_address", Name="Address", DbType="text", IsPrimaryKey=true, AutoSync=AutoSync.Never)]
[DebuggerNonUserCode()]
public string Address
{
get
{
return this._address;
}
set
{
if (((_address == value)
== false))
{
this.OnAddressChanging(value);
this.SendPropertyChanging();
this._address = value;
this.SendPropertyChanged("Address");
this.OnAddressChanged();
}
}
}
[Column(Storage="_domicileStatus", Name="DomicileStatus", DbType="text", AutoSync=AutoSync.Never)]
[DebuggerNonUserCode()]
public string DomicileStatus
{
get
{
return this._domicileStatus;
}
set
{
if (((_domicileStatus == value)
== false))
{
this.OnDomicileStatusChanging(value);
this.SendPropertyChanging();
this._domicileStatus = value;
this.SendPropertyChanged("DomicileStatus");
this.OnDomicileStatusChanged();
}
}
}
[Column(Storage="_patientID", Name="PatientID", DbType="integer", IsPrimaryKey=true, IsDbGenerated=true, AutoSync=AutoSync.Never)]
[DebuggerNonUserCode()]
public System.Nullable<int> PatientID
{
get
{
return this._patientID;
}
set
{
if ((_patientID != value))
{
if (_patients.HasLoadedOrAssignedValue)
{
throw new System.Data.Linq.ForeignKeyReferenceAlreadyHasValueException();
}
this.OnPatientIDChanging(value);
this.SendPropertyChanging();
this._patientID = value;
this.SendPropertyChanged("PatientID");
this.OnPatientIDChanged();
}
}
}
#region Parents
[Association(Storage="_patients", OtherKey="ID", ThisKey="PatientID", Name="fk_PatientsAddresses_0", IsForeignKey=true)]
[DebuggerNonUserCode()]
public Patient Patient
{
get
{
return this._patients.Entity;
}
set
{
if (((this._patients.Entity == value)
== false))
{
if ((this._patients.Entity != null))
{
Patient previousPatients = this._patients.Entity;
this._patients.Entity = null;
previousPatients.Addresses.Remove(this);
}
this._patients.Entity = value;
if ((value != null))
{
value.Addresses.Add(this);
_patientID = value.ID;
}
else
{
_patientID = null;
}
}
}
}
#endregion
public event System.ComponentModel.PropertyChangingEventHandler PropertyChanging;
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
protected virtual void SendPropertyChanging()
{
System.ComponentModel.PropertyChangingEventHandler h = this.PropertyChanging;
if ((h != null))
{
h(this, emptyChangingEventArgs);
}
}
protected virtual void SendPropertyChanged(string propertyName)
{
System.ComponentModel.PropertyChangedEventHandler h = this.PropertyChanged;
if ((h != null))
{
h(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
}
I use the following code to add an address to a patient:
PatientAddress address = new PatientAddress();
address.Address = txtAddress.Text;
address.DomicileStatus = cmbDomicileStatus.Text;
currentPatient.Addresses.Add(address);
Database.Source.PatientsAddresses.InsertOnSubmit(address);
Database.Source.SubmitChanges();
Database.Source is an instance of the class that extends DataContext in the generated code. On SubmitChanges, I receive this exception:
"Equal operator is not defined between Nullable(Of Int32) and Int32."
The message is not reported word by word, but the meaning is the same. The stack trace point to DbLinq code, more precisely to line 709 of source file DbLinq.Data.Linq.DataContext.cs. You can find the source files here: http://dblinq.codeplex.com/SourceControl/changeset/view/16800#314775 (under the body of the method SetEntityRefQueries(object entity)).
I see that the problem comes when comparing a foreign key value with a constant in an expression tree, but I couln't manage to get other information on that. Can you help me find the issue?
N.B.: the field address.PatientID (foreign key) is actually set to the correct value before the invocation of SubmitChanges.
As I mentioned in the comment above (which I'm repeating here so I can link images), your primary key should not be nullable. There should be a property in your mapping that you can change to set it, although I don't use DbLinq, so I can't give you a screenshot of it directly. Instead, here it is in the LINQ-2-SQL DBML designer (left) and the Entity Framework EDMX designer (right).
I'm not as sure about your deletion problem - that seems like it should work to me. Can you edit your question to include the whole block of your deletion code? As a preliminary guess, you're either creating a new object (instead of loading one) and then trying to delete it, or you're deleting the association without deleting the object.
As a general rule, I never delete from a database when I can avoid it - I just mark inactive. It's much easier to "undelete" that way.
Did you try: address.Patient = currentPatient
instead of: currentPatient.Addresses.Add(address)?
PatientAddress address = new PatientAddress();
address.Address = txtAddress.Text;
address.DomicileStatus = cmbDomicileStatus.Text;
address.Patient = currentPatient;
Database.Source.PatientsAddresses.InsertOnSubmit(address);
Database.Source.SubmitChanges();

MVVM Bindings not working properly

Update
Managed to fix the selectedIndex problem. I'd forgotten to set SelectedItem as well and naturally that caused a few issues.
So at 9AM this morning we got our 24 hour assignment and I have hit a brick wall.
We're supposed to create a program that allows a supervisor to Add and delete Employees and add Working Sessions, total hours and total earnings. But I am having some problems succesfully implementing this following the MVVM-Pattern. For some reason my Bindings simply aren't working and the only Solution I can see is someone looking over my project and helping me troubleshoot it.
Here is my code - I'm very sorry about having to post the entire thing but given that I have no clue where the problem is I did not see any other options. :
EmployeeModel
[Serializable]
public class WorkSessions : ObservableCollection<WorkSessionModel>
{
public WorkSessions()
{
}
}
[Serializable]
public class WorkSessionModel : INotifyPropertyChanged
{
private DateTime _dateTime;
private string _id;
private double _hours;
public WorkSessionModel()
{
}
public DateTime DateTime
{
get { return _dateTime; }
set
{
_dateTime = value;
NotifyPropertyChanged("DateTime");
}
}
public string ID
{
get { return _id; }
set
{
_id = value;
NotifyPropertyChanged("ID");
}
}
public double Hours
{
get { return _hours; }
set
{
_hours = value;
NotifyPropertyChanged("Hours");
NotifyPropertyChanged("TotalHours");
}
}
[field: NonSerialized]
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
WorkSessionModel
[Serializable]
public class WorkSessions : ObservableCollection<WorkSessionModel>
{
public WorkSessions()
{
}
}
[Serializable]
public class WorkSessionModel : INotifyPropertyChanged
{
private DateTime _dateTime;
private string _id;
private double _hours;
public WorkSessionModel()
{
}
public DateTime DateTime
{
get { return _dateTime; }
set
{
_dateTime = value;
NotifyPropertyChanged("DateTime");
}
}
public string ID
{
get { return _id; }
set
{
_id = value;
NotifyPropertyChanged("ID");
}
}
public double Hours
{
get { return _hours; }
set
{
_hours = value;
NotifyPropertyChanged("Hours");
NotifyPropertyChanged("TotalHours");
}
}
[field: NonSerialized]
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
}
EmployeeViewModel
public class EmployeeViewModel : ViewModelBase
{
private Employees _employeesModel = new Employees();
public Employees EmployeesView = new Employees();
public ObservableCollection<WorkSessionModel> WorkSessions { get; set; }
private string _id = "0";
private string _name = "noname";
private double _wage = 0;
private int _totalhours = 0;
public string ID
{
get { return _id; }
set { _id = value; RaisePropertyChanged("ID"); }
}
public string Name
{
get { return _name; }
set
{
_name = value;
RaisePropertyChanged("Name");
}
}
public double Wage
{
get { return _wage; }
set
{
_wage = value;
RaisePropertyChanged("Wage");
}
}
public int TotalHours
{
get { return _totalhours; }
set
{
_totalhours = value;
RaisePropertyChanged("TotalHours");
}
}
private EmployeeModel _selectedEmployee = new EmployeeModel();
public EmployeeModel SelectedEmployee
{
get { return _selectedEmployee; }
set
{
_selectedEmployee = value;
RaisePropertyChanged("SelectedEmployee");
}
}
private int _selectedEmployeeIndex;
public int SelectedEmployeeIndex
{
get { return _selectedEmployeeIndex; }
set
{
_selectedEmployeeIndex = value;
RaisePropertyChanged("SelectedEmployeeIndex");
}
}
#region RelayCommands
// Employee Relay Commands
public RelayCommand EmployeeAddNewCommand { set; get; }
public RelayCommand EmployeeDeleteCommand { set; get; }
public RelayCommand EmployeeNextCommand { set; get; }
public RelayCommand EmployeePrevCommand { set; get; }
public RelayCommand EmployeeTotalHoursCommand { get; set; }
#endregion
public EmployeeViewModel()
{
InitCommands();
}
private void InitCommands()
{
EmployeeAddNewCommand = new RelayCommand(EmployeeAddNewExecute, EmployeeAddNewCanExecute);
EmployeeDeleteCommand = new RelayCommand(EmployeeDeleteNewExecute, EmployeeDeleteCanExecute);
EmployeeNextCommand = new RelayCommand(EmployeeNextExecute, EmployeeNextCanExecute);
EmployeePrevCommand = new RelayCommand(EmployeePrevExecute, EmployeePrevCanExecute);
//EmployeeTotalHoursCommand = new RelayCommand(EmployeeTotalHoursExecute, EmployeeTotalHoursCanExecute);
}
//private void EmployeeTotalHoursExecute()
//{
// _selectedEmployee.TotalHours();
//}
//private bool EmployeeTotalHoursCanExecute()
//{
// return true;
//}
private void EmployeeAddNewExecute()
{
EmployeeModel newEmployee = new EmployeeModel();
EmployeesView.Add(newEmployee);
_employeesModel.Add(newEmployee);
SelectedEmployee = newEmployee;
}
private bool EmployeeAddNewCanExecute()
{
return true;
}
private void EmployeeDeleteNewExecute()
{
if (MessageBox.Show("You are about delete all submissions for Employee," + SelectedEmployee.Name + "(" + SelectedEmployee.ID +")\r\nAre you sure?", "This is a Warning!", MessageBoxButton.YesNo) == MessageBoxResult.Yes)
{
_employeesModel.Remove(SelectedEmployee);
EmployeesView.Remove(SelectedEmployee);
}
}
private bool EmployeeDeleteCanExecute()
{
if (SelectedEmployee != null)
return true;
else return false;
}
private void EmployeeNextExecute()
{
SelectedEmployeeIndex++;
}
private bool EmployeeNextCanExecute()
{
if (SelectedEmployeeIndex < EmployeesView.Count - 1)
return true;
return false;
}
private void EmployeePrevExecute()
{
SelectedEmployeeIndex--;
}
private bool EmployeePrevCanExecute()
{
if (SelectedEmployeeIndex > 0)
return true;
return false;
}
}
View
public partial class MainWindow : Window
{
public EmployeeViewModel EmployeeViewModel = new EmployeeViewModel();
public MainWindow()
{
InitializeComponent();
menu_employee.DataContext = EmployeeViewModel;
sp_employees.DataContext = EmployeeViewModel;
datagrid_employees.ItemsSource = EmployeeViewModel.EmployeesView;
grid_selectedEmployee.DataContext = EmployeeViewModel.SelectedEmployee;
}
}
I can see a few problems with your code:
When the SelectedIndex is updated, SelectedItem remains the same and vice versa.
It looks like your data binding is out of order:
The DataContext property cascades down to every child of a certain dependency object.
The code in the MainWindow constructor should probably be replaced by:
this.DataContext = EmployeeViewModel;
Then in XAML set the rest of the properties using Data Binding. The problem in your situation is that the DataContext of the selectedemployee is only set once. This means if you select another employee, then it will not update.
An example for your SelectedEmployee grid:
<Grid Name="grid_selectedEmployee" DataContext="{Binding SelectedEmployee,
UpdateSourceTrigger=PropertyChanged}">...</Grid>
One of the biggest things I see is you are setting properties, not binding them.
For example,
datagrid_employees.ItemsSource = EmployeeViewModel.EmployeesView;
You are telling your DataGrid that it's ItemsSource should be that specific object. You need to bind it to that value so you are telling it to point to that property instead. This will make your UI correctly reflect what's in your ViewModel
The other huge red flag I see is your ViewModel referencing something called and EmployeeView which leads me to believe your View and ViewModel too closely tied together.
Your ViewModel should contain all your business logic and code, while the View is usually XAML and simply reflects the ViewModel in a user-friendly way.
The View and the ViewModel should never directly reference each other (I have had my View reference my ViewModel in some rare occasions, but never the other way around)
For example, an EmployeesViewModel might contain
ObservableCollection<Employee> Employees
Employee SelectedEmployee
ICommand AddEmployeeCommand
ICommand DeleteEmployeeCommand
while your View (XAML) might look like this:
<StackPanel>
<StackPanel Orientation="Horizontal">
<Button Content="Add" Command="{Binding AddEmployeeCommand}" />
<Button Content="Delete" Command="{Binding DeleteEmployeeCommand}" />
</StackPanel>
<DataGrid ItemsSource="{Binding Employees}"
SelectedItem="{Binding SelectedEmployee}">
... etc
</DataGrid>
<UniformGrid DataContext="{Binding SelectedEmployee}" Columns="2" Rows="4">
<TextBlock Text="ID" />
<TextBox Text="{Binding Id}" />
... etc
</UniformGrid >
</StackPanel>
And the only thing you should be setting is the DataContext of the entire Window. Usually I overwrite App.OnStartup() to start up my application:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var view = new MainWindow();
var vm = new EmployeesViewModel;
view.DataContext = vm;
view.Show();
}
}
Although I suppose in your case this would also work:
public MainWindow()
{
InitializeComponent();
this.DataContext = new EmployeesViewModel();
}

Categories