Windows Phone 8.1 RT view not updating (MVVM) - xaml

I'm designing a profile page for users where they can edit their personal info. I'm using a PersonViewModel (which contains the current signed in person) to display the current info about the User. The fields to edit the user's info are bound to a validation model. After pressing the 'execute changes' button and I get a response of the server (HTTPStatusCode Ok + the altered user object), I alter the fields of the existing object according to the changes. Then I used setter injection to update my PersonViewModel... When debugging, I can see that my objects are all up-to-date but my view is still displaying the old info... What am I doing wrong?`
This is the code that get's executed when I press the button to execute my changes:
private async void ChangeInfoButton(object sender, RoutedEventArgs e)
{
User user;
List<ErrorInfo> errors;
if (_profileInformationValidationModel.TryGetUser(out user, out errors))
{
var response = await Session.Instance.DataProvider.UpdaterUserInfo(user);
if (response.IsSuccess)
{
/*SignedInUserInfo = AlteredUserInfo*/
Session.Instance.User.Information = user.Information;
_personViewModel.SetPerson(user.Information);
var d1 = new MessageDialog("Uw gegevens werden succesvol gewijzigd.");
d1.ShowAsync();
AnnulInfoButton(sender, e);
}
`
And this is the PersonViewModel:
public class PersonViewModel
{
private Person _person;
public void SetPerson(Person p)
{
_person = p;
}
public PersonViewModel(Person person)
{
_person = person;
}
public string Street
{
get { return _person.Street; }
}
public string HouseNumber
{
get { return _person.HouseNumber; }
}
public string Bus
{
get { return _person.Bus; }
}
public string Email
{
get { return _person.Email; }
}

Your view model should implement the INotifyPropertyChanged interface.
Look into using a framework like MVVM Light which does most of this work for you.
You can add it to your project using NuGet.
This is how your model and view-model should look:
public class Person
{
public string Street { get; set; }
public string HouseNumber { get; set; }
public string Bus { get; set; }
public string Email { get; set; }
}
public class PersonViewModel : System.ComponentModel.INotifyPropertyChanged
{
private Person _person;
public void SetPerson(Person person)
{
_person = person;
Street = person.Street;
HouseNumber = person.HouseNumber;
Bus = person.Bus;
Email = person.Email;
}
public PersonViewModel(Person person)
{
SetPerson(person);
}
#region Street (INotifyPropertyChanged Property)
private string _street;
public string Street
{
get { return _street; }
set
{
if (_street != value)
{
_street = value;
RaisePropertyChanged("Street");
}
}
}
#endregion
#region HouseNumber (INotifyPropertyChanged Property)
private string _houseNumber;
public string HouseNumber
{
get { return _houseNumber; }
set
{
if (_houseNumber != value)
{
_houseNumber = value;
RaisePropertyChanged("HouseNumber");
}
}
}
#endregion
#region Bus (INotifyPropertyChanged Property)
private string _bus;
public string Bus
{
get { return _bus; }
set
{
if (_bus != value)
{
_bus = value;
RaisePropertyChanged("Bus");
}
}
}
#endregion
#region Email (INotifyPropertyChanged Property)
private string _email;
public string Email
{
get { return _email; }
set
{
if (_email != value)
{
_email = value;
RaisePropertyChanged("Email");
}
}
}
#endregion
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string p)
{
var propertyChanged = PropertyChanged;
if (propertyChanged != null)
{
propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(p));
}
}
}

Related

Xamarin.Forms: Cannot connect to database

I have this database structure:
public class QRDatabase
{
readonly SQLiteAsyncConnection _database;
public QRDatabase(string dbPath)
{
_database = new SQLiteAsyncConnection(dbPath);
_database.CreateTableAsync<db_QRCODE_Type>().Wait();
}
public Task<List<db_QRCODE_Type>> GetQRCode()
{
return _database.Table<db_QRCODE_Type>().ToListAsync();
}
public Task<int> SaveQRCode(db_QRCODE_Type note)
{
if (note.ID != 0)
{
return _database.UpdateAsync(note);
}
else
{
return _database.InsertAsync(note);
}
}
public Task<int> DelteQRCode(db_QRCODE_Type note)
{
return _database.DeleteAsync(note);
}
}
This uses this type:
public class db_QRCODE_Type
{
[PrimaryKey, AutoIncrement]
public int ID { get; set; } // Identificator of column
public string firstName { get; set; } // firstname
public string lastName { get; set; } // firstname
public byte[] qrBytes { get; set; } //qr code in bytes
}
Then, in the class where I need the DB I am doing this from the tutorial here:
https://learn.microsoft.com/de-de/xamarin/get-started/quickstarts/database?pivots=windows
static QRDatabase database;
static string nameOfDB = "01db_qrs_q2go.db3";
public static QRDatabase Database
{
get
{
if (database == null)
{
database = new QRDatabase(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), nameOfDB));
}
return database;
}
}
However, I am not quite sure how this works since I am never calling "Database" even though this is where the database is supposed to be initiliased.
Now, when I try to write to the database:
db_QRCODE_Type entry = new db_QRCODE_Type();
entry.firstName = entry_firstname.Text;
entry.lastName = entry_lastname.Text;
entry.qrBytes = qrCodeBytes;
try
{
await database.SaveQRCode(entry);
}
catch
{
DependencyService.Get<IMessage>().LongAlert("Etwas hat nicht funktioniert, bitte versuche es noch einmal. Fehlercode: DB_665h");
}
It fails saying it is not set reference to an instance and goes into the catch block. I am doing everything as in the tutorial. Why is this happening?
Thank you!

XamarinForms Exception

I created a search bar with database connection. When i run it. It get an exception. i use a database that was created before.
Model class entries
public class entries
{
public entries()
{
}
public entries(string word)
{
this.word = word;
}
public entries(string word, string wordtype, string definition)
{
this.word = word;
this.wordtype = wordtype;
this.definition = definition;
}
public string word
{ get; set; }
public string wordtype
{ get; set; }
public string definition
{ get; set; }
public List<string> GetWord { get; set; }
}
Class DatabaseManager:
public class DatabaseManager
{
SQLiteConnection dbConnection;
public DatabaseManager()
{
dbConnection = DependencyService.Get<ISQLite>().GetConnection();
}
public List<string> GetWord()
{
return dbConnection.Query<string>("Select word From [entries]").ToList();
}
}
MainPage.xaml.cs:
DatabaseManager dbManager = new DatabaseManager();
private void MySearchBar_SearchButtonPressed(object sender, EventArgs e)
{
}
private void MySearchBar_TextChanged(object sender, TextChangedEventArgs e)
{
var keyword = MySearchBar.Text;
if(keyword.Length >= 1) {
var suggestions = dbManager.GetWord().Where(c => c.ToLower().Contains(keyword.ToLower()));
SuggestionListView.ItemsSource = suggestions;
SuggestionListView.IsVisible = true;
}
else
{
SuggestionListView.IsVisible = false;
}
}
This is Exception:
System.MissingMethodException: Constructor on type 'System.String' not
found.
Please Help. Thank you so much.
You might have created an Entity for the “entries” table, say for example it is,
[Table (“entries”)]
public class Entries
{
…
[Column (“word”)]
public string Word;
…
}
then change the line
dbConnection.Query<string>("Select word From [entries]").ToList();
to
dbConnection.Table<Entries>().Select(x => x.Word).ToList();
This will remove the requirement of creating one additional class as Sushi said in above comment.
Moreover, following line will throw a NullReferenceException at c.ToLower(), if any of the word contains Null into the table.
dbManager.GetWord().Where(c => c.ToLower().Contains(keyword.ToLower()));
So to get rid of this, select results which has not null values like,
dbConnection.Table<Entries>().Where(x => x.Word != null).Select(x => x.Word).ToList();

xamarin.forms binding to class property not working

In my XamarinForms project I am trying to bind a label text to a property of a class. when I pass in the object to my view the label is not being populated. can someone see what I am doing wrong?
In my view model I have
class ManagerLevelPageViewModel : INotifyPropertyChanged
{
private UserSelections _MyUserSelections;
public UserSelections MyUserSelections
{
get { return _MyUserSelections; }
set {
_MyUserSelections = value;
NotifyPropertyChanged();
}
}
public ManagerLevelPageViewModel(UserSelections _temp)
{
MyUserSelections = _temp;
MyUserSelections.selectedClientName = _temp.selectedClientName;
//myUserSelections = _myUserSelections;
//SetValues();
}
here is the class
public class UserSelections
{
public int selectedClientId { get; set; }
public string selectedClientName { get; set; }
public string selectedClientShortCode { get; set; }
public decimal selectedClientPL { get; set; }
public string TopdayIdentifier { get; set; }
}
here is the view.cs
ManagerLevelPageViewModel vm;
public ManagerLevelPage (UserSelections _myUserSelections)
{
vm = new ManagerLevelPageViewModel(_myUserSelections);
InitializeComponent ();
BindingContext = vm;
DownloadData();
}
lastly here is the xaml
<Label Text="{Binding MyUserSelections.ClientName}"/>
notify property changed
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}

xamarin.forms join query on azure sql database

I have created a Xamarin.Forms app in Visual Studio that connects to an Azure SQL Database via an Azure Mobile App. So far everything is working fine - I can do CRUD operations on the database from my Xamarin App.
However I have not yet been able to perform an inner join query on two or more tables.
I have created one such query in a View on the Database, and it works ok on the server, but my problem is that I do not know how to connect to this View from the Xamarin.Forms app.
I would really appreciate any help :-)
Thank you!
XAMARIN.FORMS SERVICE CLASS FOR A GENERIC AZURE TABLE:
public class service<T> : serviceBase<T> where T : irlm.azure.models.modelBase
{
public async Task<ObservableCollection<T>> get()
{
var items = await table.ToEnumerableAsync();
return new ObservableCollection<T>(items);
}
public async Task<T> update(T item)
{
if (item.Id == null)
await table.InsertAsync(item);
else
await table.UpdateAsync(item);
return item;
}
public async Task delete(T item)
{
await table.DeleteAsync(item);
}
}
public abstract class serviceBase<T>
{
MobileServiceClient dc;
public IMobileServiceTable<T> table;
public serviceBase()
{
dc = new MobileServiceClient(irlm.constants.appUrl);
table = dc.GetTable<T>();
}
}
XAMARIN.FORMS MODEL EXAMPLE
public abstract class modelBase
{
public string Id { get; set; }
}
public class golfClub : modelBase
{
public string name { get; set; }
}
public class golfCourse : modelBase
{
public string idClub { get; set; }
public string name { get; set; }
}
XAMARIN.FORMS VIEWMODEL:
public class viewModel<T> : INotifyPropertyChanged
{
private ObservableCollection<T> _items = new ObservableCollection<T>();
public ObservableCollection<T> items
{
get { return _items; }
set
{
_items = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
CONTENT PAGE:
irlm.azure.viewModels.viewModel<irlm.azure.models.golfClub> golfClubs = new azure.viewModels.viewModel<azure.models.golfClub>();
irlm.azure.services.service<irlm.azure.models.golfClub> dc = new azure.services.service<azure.models.golfClub>();
ListView list;
Entry txt = new Entry();
private async void BtnAdd_Clicked(object sender, EventArgs e)
{
var golfCourse = await dc.update(new irlm.azure.models.golfClub { name = txt.Text });
golfClubs.items.Add(golfCourse);
}
private async void BtnUpdate_Clicked(object sender, EventArgs e)
{
var index = golfClubs.items.IndexOf(list.SelectedItem as irlm.azure.models.golfClub);
var item = (irlm.azure.models.golfClub)list.SelectedItem;
item.name = txt.Text;
await dc.update(item);
golfClubs.items[index] = item;
}
private async void BtnRemove_Clicked(object sender, EventArgs e)
{
var item = (irlm.azure.models.golfClub)list.SelectedItem;
await dc.delete(item);
golfClubs.items.Remove((irlm.azure.models.golfClub)list.SelectedItem);
txt.Text = "";
}

Determine what fields to save in Windows Azure Table Storage

I'm trying to store an entity called Tshirt into a Windows Azure table storage along with a Blob on Windows Azure Blob storage.
That entity Tshirt contains a field called Image (byte[]) but I don't want to save that in my table.
How can I indicate in my class that I don't want to save that field?
public class Tshirt : TableServiceEntity
{
public Tshirt(string partitionKey, string rowKey, string name)
{
this.PartitionKey = partitionKey;
this.RowKey = rowKey;
this.Name = name;
this.ImageName = new Guid();
}
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
private string _color { get; set; }
public string Color
{
get { return _color; }
set { _color = value; }
}
private int _amount { get; set; }
public int Amount
{
get { return _amount; }
set { _amount = value; }
}
[NonSerialized]
private byte[] _image;
public byte[] Image
{
get { return _image; }
set { _image = value; }
}
private Guid _imageName;
public Guid ImageName
{
get { return _imageName; }
set { _imageName = value; }
}
}
The easy way is to expose the field as a pair of methods rather than an actual property:
public byte[] GetImage()
{
return _image;
}
public void SetImage(byte[] image)
{
_image = image;
}
If that's not an option, then you can remove the Image property when you're storing the entity by handling the WritingEntity event. (Credit to Neil Mackenzie)
public void AddTshirt(Tshirt tshirt)
{
var context = new TableServiceContext(_baseAddress, _credentials);
context.WritingEntity += new EventHandler<ReadingWritingEntityEventArgs>(RemoveImage);
context.AddObject("Tshirt", tshirt);
context.SaveChanges();
}
private void RemoveImage(object sender, ReadingWritingEntityEventArgs args)
{
XNamespace d = "http://schemas.microsoft.com/ado/2007/08/dataservices";
XElement imageElement = args.Data.Descendants(d + "Image").First();
imageElement.Remove();
}