Problem adding a new record in my Xamarin app - xamarin

I am using Freshsmvvm in my project and I want to display a list of operations,
this is my method from the crud
public List<Operation> GetAll()
{
try
{
return connection.Table<Operation>().ToList();
}
catch (Exception ex)
{
StatusMessage = $"Error: {ex.Message}";
}
return null;
}
In my viewModel i'm have a list and a method to obtain the saved records
private List<Operation> _listOp;
public List<Operation> ListOp
{
get { return _listOp; }
set
{
_listOp = value;
RaisePropertyChanged();
}
}
private void GetOp()
{
ListOp = App.OperationRepository.GetAll();
}
*add the GetOp method in the constructor to load in the collectionview*
public override void Init(object initData)
{
GetOp();
}
What happens is that the list does not update, I have to close the application and when I open it again, the entered record appears.
This is the list without adding a new record
This is the list with a log after restarting the app

You can use the method OnAppearing() to refresh your list.
protected override async void OnAppearing()
{
base.OnAppearing();
ListOp = App.OperationRepository.GetAll();
}

Related

Wicket 6 AjaxFormComponentUpdatingBehavior event working on first row of ListView but not for subsequent ones

I'm trying to handle a DropDownChoice onchange event in a listView that can display a modal window. It seems working fine for first element but not for subsequent added elements.
final ModalWindow modal = new ModalWindow("modal");
modal.setOutputMarkupId(true);
form.add(modal);
final ListView<CommandeFournisseurDetails> myView = new ListView<CommandeFournisseurDetails>(
"rowsList",
new PropertyModel<List<CommandeFournisseurDetails>>(this,
"rows")) {
#Override
protected void populateItem(
final ListItem<CommandeFournisseurDetails> item) {
final CommandeCollectionJDBC myCollection = new CommandeCollectionJDBC();
CommandeFournisseurDetails row = item.getModelObject();
item.add(new Label("index",
new AbstractReadOnlyModel<Integer>() {
#Override
public Integer getObject() {
return item.getIndex() + 1;
}
}));
final DropDownChoice<String> ID_PRODUIT = new DropDownChoice(
"ID_PRODUIT", new PropertyModel<String>(row,
"ID_PRODUIT"), myCollection.getProduit());
ID_PRODUIT.setOutputMarkupId(true);
ID_PRODUIT.setMarkupId("ID_PRODUIT");
ID_PRODUIT.setLabel(Model.of("Produit"));
ID_PRODUIT.setRequired(true);
AjaxFormComponentUpdatingBehavior behavior = new AjaxFormComponentUpdatingBehavior(
"onChange") {
protected void onUpdate(AjaxRequestTarget target) {
if (!ID_PRODUIT.getDefaultModelObjectAsString()
.isEmpty()) {
final PageParameters params = new PageParameters();
params.set("message",
ID_PRODUIT.getDefaultModelObjectAsString());
params.set("type", "Produit");
modal.setPageCreator(new ModalWindow.PageCreator() {
public Page createPage() {
// Use this constructor to pass a reference
// of this page.
return new ModalContentPage(modal, params);
}
});
modal.show(target);
target.add(modal);
target.add(ID_PRODUIT);
}
}
protected void onError(AjaxRequestTarget target,
RuntimeException e) {
System.out.println(e.toString());
}
};
ID_PRODUIT.add(behavior);
AbstractSubmitLink remove = new SubmitLink("removeRowLink") {
#Override
public void onSubmit() {
getList().remove(item.getModelObject());
getParent().getParent().removeAll();
};
}.setDefaultFormProcessing(false);
item.add(remove);
}
}.setReuseItems(true);
form.add(new SubmitLink("addRowLink") {
#Override
public void onSubmit() {
rows.add(new CommandeFournisseurDetails());
}
}.setDefaultFormProcessing(false));
myView.setOutputMarkupId(true);
form.add(myView);
Any idea why the other elements do not inherit the same event?
Thanks for your help.
All ID-PRODUIT dropdownchoices (the first, but also the rest) have the same markupId, thanks to:
ID_PRODUIT.setMarkupId("ID_PRODUIT");
Try giving them a unique MarkupId. Perhaps by adding the index of the listitem:
ID_PRODUIT.setMarkupId("ID_PRODUIT" + item.getIndex());
or remove that line of code altogether.

windows phone loading data from MainViewModel

Noob question probably.
I am developing a mvm wp7 app where the map shows pushpins of salons. The database is retrieved from a link.
The problem i am struggling with is that the observable collection data is not being loaded from the App._ViewModel (where the json serializer parses the database and works fine). On debugging the app shows a plain map and thats all. On returning a string attribute from the database causes a break on that code. i tried messagebox as well to show the string, still crashes.
Heres the code:
mainviewmodel.cs
public class MainViewModel
{
public bool IsDataLoaded { get; private set; }
public ObservableCollection<SalonViewModel> SalonCollection { get; private set; }
public MainViewModel()
{
IsDataLoaded = false;
}
public ObservableCollection<SalonViewModel> LoadData()
{
SalonCollection = new ObservableCollection<SalonViewModel>();
var wednesday = new Uri("http://blehbleh.txt");
WebClient wc = new WebClient();
wc.OpenReadCompleted += new OpenReadCompletedEventHandler(wc_OpenReadCompleted);
wc.OpenReadAsync(wednesday);
return SalonCollection;
}
public void wc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
try
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(ObservableCollection<SalonViewModel>));
ObservableCollection<SalonViewModel> list = serializer.ReadObject(e.Result) as ObservableCollection<SalonViewModel>;
foreach (SalonViewModel b in list)
{
SalonCollection.Add(new SalonViewModel { sid=b.sid,sname=b.sname,sgeo_lat=b.sgeo_lat,sgeo_lon=b.sgeo_lon,
}
this.IsDataLoaded = true;
}
catch (Exception ex)
{
//throw ex;
MessageBox.Show(ex.Message);
}
}
The App.cs
public partial class App : Application
{
private static MainViewModel viewModel;
public static MainViewModel _viewModel
{
get
{
if (viewModel == null)
{
viewModel = new MainViewModel();
}
return viewModel;
}
}
void LoadData()
{
if (!_viewModel.IsDataLoaded)
{
_viewModel.LoadData();
}
}
etc
Heres the mappage.cs
private void salon_map_Loaded (object sender, RoutedEventArgs e)
{
foreach (SalonViewModel Salon in App._viewModel.LoadData)
{
MessageBox.Show(Salon.sname);
Pushpin p = new Pushpin();
p.Content = Salon.sname + System.Environment.NewLine + "Rate: ";
Layer.AddChild(p, new GeoCoordinate(Salon.sgeo_lon, Salon.sgeo_lat));
}
Map1.Children.Add(Layer);
}
In your MainViewModel LoadData function, OpenReadAsync() is an asynchronous function, and thus returning SalonCollection on the next line will return an empty ObservableCollection, since the callback function wc_OpenReadCompleted has not run yet.
Also, the reason the MessageBox.Show crashes is because you are attempting to call a UI function on a non-UI thread (solution to that here: Dispatcher.Invoke() on Windows Phone 7?)
Instead of returning the ObservableCollection and manually adding children to the map from that, try binding a MapItemsControl layer of the Map to the ObservableCollection of your view model. There's a decent example of doing that here: Binding Pushpins to Bing Maps in Windows Phone

Entity Framework throwing error when updating records

Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.
I get this error, but I am the only person using the database. I am using Entity Framework 4.1 with DBContext.
I am updating my records and SQL Profiler is showing a queue being sent in. What could be the causes of this issue?
The post:
[HttpPost]
public ActionResult EditUser(User user)
{
uow.UserRepository.Update(user);
uow.Save();
return RedirectToAction("Index", "User");
}
On this call:
public void Save()
{
_context.SaveChanges();
}
This is how it is attached
public virtual void Update(TEntity entityToUpdate)
{
dbSet.Attach(entityToUpdate);
context.Entry(entityToUpdate).State = EntityState.Modified;
}
Update:
public class UnitOfWork : IDisposable
{
private StudentSchedulingEntities _context = new StudentSchedulingEntities();
private GenericRepository<User> userRepository;
private GenericRepository<UserRole> userRoleRepository;
private bool disposed = false;
public GenericRepository<User> UserRepository
{
get
{
if (this.userRepository == null)
{
this.userRepository = new GenericRepository<User>(_context);
}
return userRepository;
}
}
public GenericRepository<UserRole> UserRoleRepository
{
get
{
if (this.userRoleRepository == null)
{
this.userRoleRepository = new GenericRepository<UserRole>(_context);
}
return userRoleRepository;
}
}
public void Save()
{
_context.SaveChanges();
}
protected virtual void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
_context.Dispose();
}
}
this.disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
The ID field must be there in order to update the information properly. Otherwise, it will be throw a null. (I forgot to put the hidden field for ID in)

WP7 Developpement : How to make the program wait until the end of an EventHandler?

When my view wants the value of LogoStation, it returns null because my program has not yet executed LoadStation_Completed.
I want my program waits that LoadStation_Completed is executed before continuing.
Thx
public class Infos
{
#region propriétés
private DataServiceCollection<SyndicObject> _infosStation;
public DataServiceCollection<SyndicObject> InfosStation
{
get
{
return _infosStation;
}
set
{
_infosStation = value;
}
}
#endregion
string nameStation;
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs(propertyName));
}
}
private ImageSource _logoStation;
public ImageSource LogoStation
{
get
{
return _logoStation;
}
set
{
_logoStation = value;
NotifyPropertyChanged("LogoStation");
}
}
public Infos(string station)
{
nameStation = station;
getInfos();
}
public void getInfos()
{
SyndicationContext service = new SyndicationContext(new Uri("http://test/817bee9d-faf4-4680-9d05-e41c2c90ae5a/"));
IQueryable<SyndicObject> requete = (from objectSki in service.Objects
where objectSki.NOMSTATION == nameStation
select objectSki);
Deployment.Current.Dispatcher.BeginInvoke(() =>
{
InfosStation = new DataServiceCollection<SyndicObject>();
InfosStation.LoadCompleted += new EventHandler<LoadCompletedEventArgs>(InfoStation_LoadCompleted);
InfosStation.LoadAsync(requete);
}
);
}
void InfoStation_LoadCompleted(object sender, LoadCompletedEventArgs e)
{
LogoStation = new BitmapImage(new Uri(#"http://test/upload/" + InfosStation[0].LOGO, UriKind.Absolute));
}
}
By using the property setter you are using NotifyPropertyChanged (correctly) to tell the UI bound to LogoStation that it has been updated. This should mean that the UI will display nothing initially and then the image when the load has completed.
Without seeing your view code what you have here looks correct - apart from the fact that your Infos class doesn't inherit from INotifyPropertyChanged. This means that the event never gets sent.
Update your class definition and you should be good to go.

(MVP Pattern) How to forward error messages from Presenter to View?

I have a method where the user can search for a article number and if its available in the database the articlenumber gets bound to a BindingList. Now I want to let the user know if the article is not available in database. How do I do that the right way?
Just pass the message errorMessage to my interface method?
Presenter:
string errorMessage;
_view.ErrorMessage(errorMessage);
View:
public void ErrorMessage(string errorMessage)
{
MessageBox.Show(errorMessage);
}
Would you do it the same way?
We bubble an event. In the presenter you register that event:
public event PresenterEventHandler Message;
And then raise it like so:
PresenterEventArgs pe = new PresenterEventArgs("Error message", Status.Error);
this.Message(this, pe);
Then in the view:
protected override void OnInit(EventArgs e)
{
this.presenter = new MyPresenter(this, MyBusinessService.Instance);
this.presenter.Message += new PresenterEventHandler(presenter_Message);
}
void presenter_Message(object sender, PresenterEventArgs pe)
{
// display error message
}
You can pass different types of statuses back to the view in this way, and not just error messages. We have Success, Error, Locked, Warning, Help.
In the case of error messages I would call some base functionality. This way you could choose wether to update the status window on the bottom left and/or display a modal message box.
In the presenter:
_windowManager.NoItemFound(errorMessage)
In the window manager:
_statusBox.Text = errorMessage; MessageBox.Show(errorMessage);
We should not re-invent the wheel ....
You should simply throw an exception in your model.
Then, the view will catch the exception using a try catch block.
In the "catch", show your message box.
If its MVP - Passive View, then the View interface should have a property that could read:
public interface IArticleListView {
// more stuff here...
bool ErrorMessageVisible { set; }
string ErrorMessage { set; }
// more stuff here...
int ArticleNumber { get; }
}
public interface IPresenter {
public void Update();
}
public class ArticleListPresenter : IPresenter {
IViewArticleList _view;
public ArticleListPresenter(IArticleListView view) {
this._view = view;
// you could update the view here or with an update method,
// completely up to you.
}
// Assuming you are using a fine grained presenter
public void HandleArticleNumberSearch() {
bool articleNotFound;
// search for the article ...
if ( articleNotFound ) {
this._view.ErrorMessageVisible = true;
this._view.ErrorMessage = string.Format("The article #{0} was not found.", number);
}
}
}
public class ArticleList : Page, IArticleListView {
ArticleListPresenter _presenter;
public bool ErrorMessageVisible {
set { this.lblErrorMessage.Visible = value; }
}
public bool ErrorMessage {
set { this.lblErrorMessage.Text = value; }
}
public int ArticleNumber {
// You have to do some sort of validation here, but I'll keep it simple
get { return Integer.Parse(this.txtArticleNumber.Text); }
}
protected override void OnInit(EventArgs e) {
this._presenter = new ArticleListPresenter(this);
}
protected void Page_Load(object sender, EventArgs e) {
// this implementation keeps the state in the View, and updates it
// in the presenter: Passive View
if(!this.IsPostBack) {
this._presenter.Update();
}
}
protected void OnSearchArticleButtonClick(object sender, EventArgs e) {
this._presenter.HandleArticleNumberSearch();
}
}
That's what I do.
Another way I've read about would be for the model to know how to show an error (perhaps by an ErrorMessagePresenter) so the error is detached from the original presenter.
I haven't really found a use for that, for me, it always ends in the presenter and view implementing both interfaces.

Resources