Reputation: 51
Hello new to Xamarin form. I have a listview and I can pull up the information when the item is selected similar to the template provided in Visual Studio 2017 xamarin project.
Wish the template was more complete because adding and updating works great but I'm having trouble creating the delete method. The data is deleted from SQLite but the ObservableCollection doesn't refresh.
I tried copying similar logic from the adding and updating to the delete. I tried adding another message center method into my constructor but it's not being hit when debugging like adding. Not sure what I am missing. Over my head still.
Here is the listview and its working great
<ContentPage.ToolbarItems>
<ToolbarItem Text="-" Command="{Binding ExecuteDeleteAllCommand}"></ToolbarItem>
<ToolbarItem Text="+" Clicked="InsertAuditClicked"></ToolbarItem>
</ContentPage.ToolbarItems>
<ContentPage.Padding>
<OnIdiom>10, 10, 10, 10</OnIdiom>
</ContentPage.Padding>
<ContentPage.Content>
<StackLayout>
<ListView x:Name="AuditsListView"
ItemsSource="{Binding AuditsCollection}"
VerticalOptions="FillAndExpand"
HasUnevenRows="true"
RefreshCommand="{Binding LoadAuditsCommand}"
IsPullToRefreshEnabled="true"
IsRefreshing="{Binding IsBusy, Mode=OneWay}"
CachingStrategy="RecycleElement"
ItemSelected="OnAuditSelected">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<StackLayout Grid.Column="0">
<!-- <Label Text="{Binding Id}"
LineBreakMode="NoWrap"
Style="{DynamicResource ListAuditTextStyle}"
FontSize="16"></Label>-->
<Label Text="{Binding AuditId}"
Style="{DynamicResource ListAuditTextStyle}"
FontSize="16"></Label>
<Label Text="{Binding AuditCommand}"
LineBreakMode="NoWrap"
Style="{DynamicResource ListAuditDetailTextStyle}"
FontSize="13"></Label>
</StackLayout>
<StackLayout Grid.Column="1" VerticalOptions="CenterAndExpand" HorizontalOptions="EndAndExpand">
<Label Text=">" FontSize="18"></Label>
</StackLayout>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
Here code behind
{
AuditsViewModel ViewModel;
public AuditsPage()
{
InitializeComponent();
BindingContext = ViewModel = new AuditsViewModel();
}
async void OnAuditSelected(object s, SelectedItemChangedEventArgs e)
{
var m = e.SelectedItem as AuditModel;
if (m == null)
return;
await Navigation.PushAsync(new AuditDetailPage(new AuditDetailViewModel(m))); // (new AuditDetailPage(new AuditDetailViewModel(m)));
AuditsListView.SelectedItem = null;
}
async void InsertAuditClicked(object sender, EventArgs e)
{
await Navigation.PushModalAsync(new NavigationPage(new AuditNewPage()));
}
protected override void OnAppearing()
{
base.OnAppearing();
if (ViewModel.AuditsCollection.Count == 0)
ViewModel.LoadAuditsCommand.Execute(null);
}
}
Here is view model
namespace AuditTest.ViewModels
{
public class AuditsViewModel : BaseViewModel
{
public ObservableCollection<AuditModel> AuditsCollection { get; set; }
public Command LoadAuditsCommand { get; set; }
public AuditsViewModel()
{
Title = "Browse";
AuditsCollection = new ObservableCollection<AuditModel>();
LoadAuditsCommand = new Command(async () => await ExecuteLoadAuditsCommand());
MessagingCenter.Subscribe<AuditNewPage, AuditModel>(this, "AddAudit", async (o, a) =>
{
var n = a as AuditModel;
AuditsCollection.Add(n);
await App.MobileDataBase.InsertAuditAsync(n);
});
//MessagingCenter.Subscribe<AuditDetailPage, AuditModel>(this, "DeleteAudit", async (o, a) =>
//{
// var n = a as AuditModel;
// AuditsCollection.Remove(n);
// await App.MobileDataBase.DeleteAuditAsync(n);
//});
}
async Task ExecuteLoadAuditsCommand()
{
if (IsBusy)
return;
IsBusy = true;
try
{
AuditsCollection.Clear();
var a = await App.MobileDataBase.GetAuditsAsync(true); // var a = await DataSource.GetAuditsAsync(true);
foreach (var i in a)
{
AuditsCollection.Add(i);
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
}
finally
{
IsBusy = false;
}
}
}
}
Got a toolbar with a click event. Here is the code behind
using AuditTest.Models;
using Xamarin.Forms;
using AuditTest.Views;
using System.Threading.Tasks;
namespace AuditTest.ViewModels
{
public class AuditDetailViewModel : BaseViewModel
{
public AuditModel AuditDetail { get; set; }
public AuditDetailViewModel(AuditModel m = null)
{
Title = m.AuditId.ToString(); // m?.AuditId;
AuditDetail = m;
}
public Command ExecuteEditAuditCommand
{
get
{
return new Command(async () =>
{
await DataSource.UpdateAuditAsync(AuditDetail);
});
}
}
public Command ExecuteDeleteAuditCommand
{
get
{
return new Command(async () =>
{
await App.MobileDataBase.DeleteAuditAsync(AuditDetail); // DataSource.DeleteAuditAsync(AuditDetail.AuditId));
});
}
}
public Task TestUpdateCommand()
{
Task<bool> tt = App.MobileDataBase.UpdateAuditAsync(AuditDetail);
return tt;
}
public Task TestDeleteCommand()
{
Task<bool> tt = App.MobileDataBase.DeleteAuditAsync(AuditDetail);
MessagingCenter.Send(this, "DeleteAudit", this.AuditDetail); // await ViewModel.ExecuteDeleteAuditCommand(); // App.MobileDataBase.DeleteAuditAsync();
return tt;
}
}
}
Playing around with different properties and methods but here is the view model for the content page
using AuditTest.Models;
using Xamarin.Forms;
using AuditTest.Views;
using System.Threading.Tasks;
namespace AuditTest.ViewModels
{
public class AuditDetailViewModel : BaseViewModel
{
public AuditModel AuditDetail { get; set; }
public AuditDetailViewModel(AuditModel m = null)
{
Title = m.AuditId.ToString(); // m?.AuditId;
AuditDetail = m;
}
public Command ExecuteEditAuditCommand
{
get
{
return new Command(async () =>
{
await DataSource.UpdateAuditAsync(AuditDetail);
});
}
}
public Command ExecuteDeleteAuditCommand
{
get
{
return new Command(async () =>
{
await App.MobileDataBase.DeleteAuditAsync(AuditDetail); // DataSource.DeleteAuditAsync(AuditDetail.AuditId));
});
}
}
public Task TestUpdateCommand()
{
Task<bool> tt = App.MobileDataBase.UpdateAuditAsync(AuditDetail);
return tt;
}
public Task TestDeleteCommand()
{
Task<bool> tt = App.MobileDataBase.DeleteAuditAsync(AuditDetail);
MessagingCenter.Send(this, "DeleteAudit", this.AuditDetail); // await ViewModel.ExecuteDeleteAuditCommand(); // App.MobileDataBase.DeleteAuditAsync();
return tt;
}
}
}
Upvotes: 0
Views: 445
Reputation: 51
Fixed. Thank you Jason you are awesome! It works now.
Un-commented and changed the message center subscription on the ViewModel constructor to point to the other ViewModel sending
MessagingCenter.Subscribe<AuditDetailViewModel, AuditModel>(this, "DeleteAudit", async (o, a) =>
{
var n = a as AuditModel;
AuditsCollection.Remove(n);
await App.MobileDataBase.DeleteAuditAsync(n);
});
Public Method on other ViewModel has this still
public void MethodDeleteCommand()
{
MessagingCenter.Send(this, "DeleteAudit", this.AuditDetail);
}
Upvotes: 0