Xamarin MVVM 从另一个页面删除列表视图项
Xamarin MVVM Delete Listview Item from Another Page
你好 Xamarin 表单的新手。我有一个列表视图,我可以在选择项目时提取信息,类似于 Visual Studio 2017 xamarin 项目中提供的模板。
希望模板更完整,因为添加和更新效果很好,但我在创建删除方法时遇到了问题。数据已从 SQLite 中删除,但 ObservableCollection 未刷新。
我尝试将类似的逻辑从添加和更新复制到删除。我尝试将另一个消息中心方法添加到我的构造函数中,但是在像添加一样调试时它没有被命中。不知道我错过了什么。还在我头上。
这是列表视图,效果很好
<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>
这里是后面的代码
{
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);
}
}
这是视图模型
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;
}
}
}
}
获得了带有点击事件的工具栏。这是背后的代码
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;
}
}
}
尝试使用不同的属性和方法,但这里是内容页面的视图模型
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;
}
}
}
已修复。谢谢杰森,你太棒了!现在可以使用了。
取消评论并将 ViewModel 构造函数上的消息中心订阅更改为指向其他 ViewModel 发送
MessagingCenter.Subscribe<AuditDetailViewModel, AuditModel>(this, "DeleteAudit", async (o, a) =>
{
var n = a as AuditModel;
AuditsCollection.Remove(n);
await App.MobileDataBase.DeleteAuditAsync(n);
});
Public 其他 ViewModel 上的方法仍然如此
public void MethodDeleteCommand()
{
MessagingCenter.Send(this, "DeleteAudit", this.AuditDetail);
}
你好 Xamarin 表单的新手。我有一个列表视图,我可以在选择项目时提取信息,类似于 Visual Studio 2017 xamarin 项目中提供的模板。
希望模板更完整,因为添加和更新效果很好,但我在创建删除方法时遇到了问题。数据已从 SQLite 中删除,但 ObservableCollection 未刷新。
我尝试将类似的逻辑从添加和更新复制到删除。我尝试将另一个消息中心方法添加到我的构造函数中,但是在像添加一样调试时它没有被命中。不知道我错过了什么。还在我头上。
这是列表视图,效果很好
<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>
这里是后面的代码
{
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);
}
}
这是视图模型
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;
}
}
}
}
获得了带有点击事件的工具栏。这是背后的代码
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;
}
}
}
尝试使用不同的属性和方法,但这里是内容页面的视图模型
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;
}
}
}
已修复。谢谢杰森,你太棒了!现在可以使用了。
取消评论并将 ViewModel 构造函数上的消息中心订阅更改为指向其他 ViewModel 发送
MessagingCenter.Subscribe<AuditDetailViewModel, AuditModel>(this, "DeleteAudit", async (o, a) =>
{
var n = a as AuditModel;
AuditsCollection.Remove(n);
await App.MobileDataBase.DeleteAuditAsync(n);
});
Public 其他 ViewModel 上的方法仍然如此
public void MethodDeleteCommand()
{
MessagingCenter.Send(this, "DeleteAudit", this.AuditDetail);
}