源碼地址:https://github.com/l2999019/DemoAppgit
能夠Star一下,隨意 - -github
呃 也有半個月沒更新了. 原本這篇的Demo早就寫完了,文章也構思好了.遲遲沒發佈..是由於實在太忙..json
項目要上線..各類 大家懂的..後端
正遇上本身十一人生大事..結婚..因此..忙的那叫一個腳不沾地啊.api
使用咱們前面所學的技術,寫一個增刪改查.網絡
效果以下:app
廢話很少說,直接開始吧.async
列表ListView,採用繼承重寫的方式,實現簡易的下拉刷新ide
採用HttpClient的方式訪問後端的WebAPI.
使用了一系列的Xamarin提供的插件.
採用了MVVM的方式,來編寫咱們的業務代碼.
前面咱們說過,咱們訪問的是後端WebAPI,內容很簡單..就是一個增刪改查.
多餘的我就很少說了,直接貼出代碼以下:
public class ValuesController : ApiController { // GET api/values [HttpGet] public List<ContextTable> Get(int page,int count) { using (Models.School_TestEntities entites = new Models.School_TestEntities()) { var date= entites.ContextTable.OrderBy(c => c.ID).Skip((page - 1) * count).Take(count).ToList(); return date; } } // PUT api/values/5 public bool UpdateDate(Models.ContextTable datemodel) { // var date = JsonConvert.DeserializeObject<Models.ContextTable>(value); using (Models.School_TestEntities entites = new Models.School_TestEntities()) { var model = entites.ContextTable.Where(a => a.ID == datemodel.ID).FirstOrDefault(); model.Title = datemodel.Title; model.AddTime = datemodel.AddTime; model.Context = datemodel.Context; if (entites.SaveChanges() > 0) { return true; } return false; } } public bool AddDate(Models.ContextTable model) { var date = model; using (Models.School_TestEntities entites = new Models.School_TestEntities()) { entites.ContextTable.Add(date); if (entites.SaveChanges() >0) { return true; } } return false; } // DELETE api/values/5 public bool Delete(int id) { using (Models.School_TestEntities entites = new Models.School_TestEntities()) { var date = entites.ContextTable.Where(a => a.ID == id).FirstOrDefault(); entites.ContextTable.Remove(date); if (entites.SaveChanges() > 0) { return true; } return false; } } }
就是編寫一個訪問WebAPI用的倉儲.代碼以下:
public class ContextDataStore { HttpClient client; string RestUrl = "http://192.168.3.74:53470/api/values"; public ContextDataStore() { client = new HttpClient(); client.MaxResponseContentBufferSize = 256000; } public async Task<bool> AddItemAsync(ContextModel item) { var uri = new Uri(RestUrl+ "/AddDate/"); var json = JsonConvert.SerializeObject(item); var content = new StringContent(json); content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); var response = await client.PostAsync(uri, content); if (response.IsSuccessStatusCode) { var date = await response.Content.ReadAsStringAsync(); return Convert.ToBoolean(date); } return false; } public async Task<bool> UpdateItemAsync(ContextModel item) { var uri = new Uri(RestUrl + "/UpdateDate/"); var json = JsonConvert.SerializeObject(item); var content = new StringContent(json); content.Headers.ContentType = new MediaTypeHeaderValue("application/json"); var response = await client.PostAsync(uri, content); if (response.IsSuccessStatusCode) { var date = await response.Content.ReadAsStringAsync(); return Convert.ToBoolean(date); } return false; } public async Task<bool> DeleteItemAsync(int id) { var uri = new Uri(string.Format(RestUrl + "/Delete/?id=" + id, string.Empty)); var response = await client.DeleteAsync(uri); if (response.IsSuccessStatusCode) { var content = await response.Content.ReadAsStringAsync(); return Convert.ToBoolean(content); } return false; } public async Task<IEnumerable<ContextModel>> GetItemsAsync(int page,int rows) { var uri = new Uri(string.Format(RestUrl+"/Get/?page="+page+ "&count=" + rows, string.Empty)); var response = await client.GetAsync(uri); List<ContextModel> Items = new List<ContextModel>(); if (response.IsSuccessStatusCode) { var content = await response.Content.ReadAsStringAsync(); try { Items = JsonConvert.DeserializeObject<List<ContextModel>>(content); } catch (Exception ex) { } } return Items; } }
詳解請查看系列目錄中的MVVM篇
代碼以下(註釋中有解釋):
public class ContextViewModel: INotifyPropertyChanged { //初始化倉儲 public ContextDataStore DataStore =new ContextDataStore(); //設置綁定對象 public ObservableCollection<ContextModel> Items { get; set; } //設置刷新命令 public Command LoadItemsCommand { get; set; } public event PropertyChangedEventHandler PropertyChanged; private int page = 1; private int rows = 10; /// <summary> /// 初始化各類數據與監聽 /// </summary> public ContextViewModel() { Items = new ObservableCollection<ContextModel>(); LoadItemsCommand = new Command(async () => await ExecuteLoadItemsCommand()); //監聽添加的消息 MessagingCenter.Subscribe<ContextModelPage, ContextModel>(this, "AddItem", async (obj, item) => { var _item = item as ContextModel; var date = await DataStore.AddItemAsync(_item); if (date) { LoadDate(); await obj.DisplayAlert("提示", "添加成功!", "關閉"); await obj.Navigation.PopAsync(); } else { await obj.DisplayAlert("提示", "添加失敗!", "關閉"); } }); //監聽更新的消息 MessagingCenter.Subscribe<ContextModelPage, ContextModel>(this, "UpdateItem", async (obj, item) => { var date = await DataStore.UpdateItemAsync(item); if (date) { LoadDate(); await obj.DisplayAlert("提示", "修改爲功!", "關閉"); await obj.Navigation.PopAsync(); } else { await obj.DisplayAlert("提示", "修改失敗!", "關閉"); } }); ExecuteLoadItemsCommand(); } /// <summary> /// 刪除的方法 /// </summary> /// <param name="id"></param> /// <returns></returns> public async Task<bool> DeleteItem(int id) { var date = await DataStore.DeleteItemAsync(id); if (date) { var item = Items.Where(a => a.ID == id).FirstOrDefault(); Items.Remove(item); OnPropertyChanged("Items"); } return date; } /// <summary> /// 加載數據的命令 /// </summary> /// <returns></returns> async Task ExecuteLoadItemsCommand() { try { //Items.Clear(); var items = await DataStore.GetItemsAsync(page,rows); foreach (var item in items) { Items.Add(item); } OnPropertyChanged("Items"); page++; } catch (Exception ex) { } } /// <summary> /// 從新刷新數據 /// </summary> private async void LoadDate() { Items.Clear(); page = 1; var items = await DataStore.GetItemsAsync(page, rows); foreach (var item in items) { Items.Add(item); } OnPropertyChanged("Items"); page++; } protected virtual void OnPropertyChanged(string propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } }
嗯.仍是說明一下 這個ViewModel就相似於MVC中的控制器,起到一個承上啓下的做用.與頁面交互並把這些交互信息傳遞給倉儲,由倉儲來訪問WebAPI
咱們建立一個ContentPage頁面以下:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:DemoApp.HTTPClientDemo.ViewModels" xmlns:Controls="clr-namespace:DemoApp.HTTPClientDemo;" x:Class="DemoApp.HTTPClientDemo.ListViewPage"> <ContentPage.ToolbarItems> <ToolbarItem Text="添加" Order="Default" Clicked="ToolbarItem_Clicked" /> </ContentPage.ToolbarItems> <ContentPage.Content> <StackLayout> <Controls:MyListView ItemsSource="{Binding Items}" VerticalOptions="FillAndExpand" HasUnevenRows="true" LoadMoreCommand="{Binding LoadItemsCommand}" x:Name="listdate" > <ListView.ItemTemplate> <DataTemplate > <ViewCell> <ViewCell.ContextActions> <MenuItem CommandParameter="{Binding}" Clicked="MenuItem_Clicked" Text="修改" /> <MenuItem x:Name="DeleteBtn" CommandParameter="{Binding ID}" Clicked="MenuItem_Clicked_1" Text="刪除" IsDestructive="True" /> </ViewCell.ContextActions> <StackLayout Padding="10"> <Label Text="{Binding Title}" LineBreakMode="NoWrap" Style="{DynamicResource ListItemTextStyle}" FontSize="16"/> <Label Text="{Binding AddTime}" LineBreakMode="NoWrap" Style="{DynamicResource ListItemDetailTextStyle}" FontSize="13"/> </StackLayout> </ViewCell> </DataTemplate> </ListView.ItemTemplate> </Controls:MyListView> </StackLayout> </ContentPage.Content> </ContentPage>
這個ContentPage中,咱們使用了StackLayout佈局,ListView,ToolbarItem 等控件.綁定了咱們前面編寫的ContextViewModel(後臺代碼綁定的,在下面)
編寫這個ContentPage的後臺代碼以下:
public partial class ListViewPage : ContentPage { ContextViewModel viewModel; public ListViewPage() { InitializeComponent(); this.BindingContext = viewModel = new ContextViewModel(); } private void MenuItem_Clicked(object sender, EventArgs e) { var mi = ((MenuItem)sender); ContextModel date = mi.CommandParameter as ContextModel; Navigation.PushAsync(new ContextModelPage()); MessagingCenter.Send<ListViewPage,ContextModel>(this, "GetModel", date); } private async void MenuItem_Clicked_1(object sender, EventArgs e) { var mi = ((MenuItem)sender); int id = Convert.ToInt32( mi.CommandParameter); var date = await viewModel.DeleteItem(id); if (!date) { await DisplayAlert("提示", "刪除失敗,請檢查網絡", "肯定"); } } private void ToolbarItem_Clicked(object sender, EventArgs e) { Navigation.PushAsync(new ContextModelPage()); } }
這裏,咱們綁定了ContextViewModel,而後編寫了界面上的各類交互事件.
以上,咱們的列表也就算完成了,下面咱們來看看咱們的增長和修改頁面.(也就是顯示詳細數據的頁面)
以下:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="DemoApp.HTTPClientDemo.ContextModelPage"> <ContentPage.Content> <StackLayout> <Label Text="標題:" /> <Entry Placeholder="請輸入標題" x:Name="titel" /> <Label Text="時間:" /> <DatePicker Format="yyyy-MM-dd" x:Name="times" /> <Label Text="內容:" /> <Editor HorizontalOptions="FillAndExpand" HeightRequest="200" x:Name="contexts" /> <Button Text="保存" x:Name="BtnSave" Clicked="BtnSave_Clicked" ></Button> </StackLayout> </ContentPage.Content> </ContentPage>
這裏咱們採用了前面系列中講過的Label ,Entry,DatePicker ,Editor ,編寫後臺代碼以下:
public partial class ContextModelPage : ContentPage { private int isUpdate = 0; public ContextModelPage() { InitializeComponent(); MessagingCenter.Subscribe<ListViewPage, ContextModel>(this, "GetModel", (obj, item) => { //DisplayAlert("提示", "傳過來的參數爲" + item, "肯定"); this.times.Date = item.AddTime.Value; this.titel.Text = item.Title; this.contexts.Text = item.Context; isUpdate = item.ID; }); } private void BtnSave_Clicked(object sender, EventArgs e) { if (isUpdate>0) { ContextModel model = new ContextModel(); model.AddTime = times.Date; model.Context = contexts.Text; model.Title = titel.Text; model.ID = isUpdate; MessagingCenter.Send(this, "UpdateItem", model); } else { ContextModel model = new ContextModel(); model.AddTime = times.Date; model.Context = contexts.Text; model.Title = titel.Text; MessagingCenter.Send(this, "AddItem", model); } } protected override void OnDisappearing() { MessagingCenter.Unsubscribe<ListViewPage, ContextModel>(this, "GetModel"); base.OnDisappearing(); } }
這裏,咱們編寫頁面的點擊等交互事件,而後咱們採用通信中心(MessagingCenter)的方式來傳遞修改和刪除的信息給後臺的ViewModel.
至此,就完成了整個的簡易增刪改查的編寫.
本系列到此,就已經進行了一大半了..後面會繼續更新一些安卓庫的綁定等內容,敬請期待.