C#使用Xamarin开发可移植移动应用进阶篇(10.综合演练,来一份增删改查CRUD)

简介: 原文:C#使用Xamarin开发可移植移动应用进阶篇(10.综合演练,来一份增删改查CRUD)前言 系列目录 C#使用Xamarin开发可移植移动应用目录 源码地址:https://github.
原文: C#使用Xamarin开发可移植移动应用进阶篇(10.综合演练,来一份增删改查CRUD)

前言

系列目录

C#使用Xamarin开发可移植移动应用目录

源码地址:https://github.com/l2999019/DemoApp

可以Star一下,随意 - -

说点什么..

呃 也有半个月没更新了. 本来这篇的Demo早就写完了,文章也构思好了.迟迟没发布..是因为实在太忙..

项目要上线..各种  你们懂的..

正赶上自己十一人生大事..结婚..所以..忙的那叫一个脚不沾地啊.

今天的学习内容?

使用我们前面所学的技术,写一个增删改查.

效果如下:

 

 

正文

废话不多说,直接开始吧.

1.采用了的技术

   列表ListView,采用继承重写的方式,实现简易的下拉刷新

   采用HttpClient的方式访问后端的WebAPI.

   使用了一系列的Xamarin提供的插件.

   采用了MVVM的方式,来编写我们的业务代码.

2.WebAPI

   前面我们说过,我们访问的是后端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;

            }
        }
    }

3.编写服务仓储

就是编写一个访问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;
        }

    }

 

4.编写ViewModel来与界面进行绑定交互

详解请查看系列目录中的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

5.编写界面,绑定数据

我们创建一个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.

 

至此,就完成了整个的简易增删改查的编写.

 

 

写在最后

本系列到此,就已经进行了一大半了..后面会继续更新一些安卓库的绑定等内容,敬请期待.

 

目录
相关文章
|
16天前
|
物联网 C# C语言
物联网开发中C、C++和C#哪个更好用
在物联网(IoT)开发中,C、C++和C#各有优缺点,适用场景不同。C语言性能高、资源占用低,适合内存和计算能力有限的嵌入式系统,但开发复杂度高,易出错。C++支持面向对象编程,性能优秀,适用于复杂应用,但学习曲线陡峭,编译时间长。C#易于学习,与.NET框架结合紧密,适合快速开发Windows应用,但性能略低,平台支持有限。选择语言需根据具体项目需求、复杂性和团队技术栈综合考虑。
|
2月前
|
Android开发 iOS开发 C#
Xamarin:用C#打造跨平台移动应用的终极利器——从零开始构建你的第一个iOS与Android通用App,体验前所未有的高效与便捷开发之旅
【8月更文挑战第31天】Xamarin 是一个强大的框架,允许开发者使用单一的 C# 代码库构建高性能的原生移动应用,支持 iOS、Android 和 Windows 平台。作为微软的一部分,Xamarin 充分利用了 .NET 框架的强大功能,提供了丰富的 API 和工具集,简化了跨平台移动应用开发。本文通过一个简单的示例应用介绍了如何使用 Xamarin.Forms 快速创建跨平台应用,包括设置开发环境、定义用户界面和实现按钮点击事件处理逻辑。这个示例展示了 Xamarin.Forms 的基本功能,帮助开发者提高开发效率并实现一致的用户体验。
90 0
|
2月前
|
开发者 iOS开发 C#
Uno Platform 入门超详细指南:从零开始教你打造兼容 Web、Windows、iOS 和 Android 的跨平台应用,轻松掌握 XAML 与 C# 开发技巧,快速上手示例代码助你迈出第一步
【8月更文挑战第31天】Uno Platform 是一个基于 Microsoft .NET 的开源框架,支持使用 C# 和 XAML 构建跨平台应用,适用于 Web(WebAssembly)、Windows、Linux、macOS、iOS 和 Android。它允许开发者共享几乎全部的业务逻辑和 UI 代码,同时保持原生性能。选择 Uno Platform 可以统一开发体验,减少代码重复,降低开发成本。安装时需先配置好 Visual Studio 或 Visual Studio for Mac,并通过 NuGet 或官网下载工具包。
82 0
|
2月前
|
开发者 Apache 程序员
揭秘Apache Wicket:页面生命周期背后的神秘力量!
【8月更文挑战第31天】李工是一位热爱Web开发的程序员,近日在技术博客上分享了他对Apache Wicket框架的学习心得,特别是页面生命周期的理解。他认为掌握Wicket页面生命周期对于开发富交互式Web应用至关重要。他通过一个简单的计数器应用示例,详细解释了Wicket的组件化设计理念以及页面和组件在生命周期中的变化。
32 0
|
2月前
|
前端开发 开发者 Apache
揭秘Apache Wicket项目结构:如何打造Web应用的钢铁长城,告别混乱代码!
【8月更文挑战第31天】Apache Wicket凭借其组件化设计深受Java Web开发者青睐。本文详细解析了Wicket项目结构,帮助你构建可维护的大型Web应用。通过示例展示了如何使用Maven管理依赖,并组织页面、组件及业务逻辑,确保代码清晰易懂。Wicket提供的页面继承、组件重用等功能进一步增强了项目的可维护性和扩展性。掌握这些技巧,能够显著提升开发效率,构建更稳定的Web应用。
78 0
|
2月前
|
前端开发 程序员 API
从后端到前端的无缝切换:一名C#程序员如何借助Blazor技术实现全栈开发的梦想——深入解析Blazor框架下的Web应用构建之旅,附带实战代码示例与项目配置技巧揭露
【8月更文挑战第31天】本文通过详细步骤和代码示例,介绍了如何利用 Blazor 构建全栈 Web 应用。从创建新的 Blazor WebAssembly 项目开始,逐步演示了前后端分离的服务架构设计,包括 REST API 的设置及 Blazor 组件的数据展示。通过整合前后端逻辑,C# 开发者能够在统一环境中实现高效且一致的全栈开发。Blazor 的引入不仅简化了 Web 应用开发流程,还为习惯于后端开发的程序员提供了进入前端世界的桥梁。
72 0
|
2月前
|
存储 测试技术 C#
Blazor WebAssembly 开启离线应用开发新时代!C# 与.NET 助力,打造高性能跨平台新体验!
【8月更文挑战第31天】在互联网快速发展的今天,用户对Web应用体验的要求日益提高,尤其在无网络环境下使用应用的需求愈发明显。Blazor WebAssembly 应运而生,它基于 WebAssembly 技术,允许开发者利用 C# 和 .NET 构建交互式 Web 应用,无需服务器支持即可在浏览器中运行,从而实现离线使用。Blazor WebAssembly 具有使用熟悉的技术栈、高性能、离线支持以及跨平台等优势。开发者可通过安装开发工具、创建项目、编写代码、调试测试及发布应用几个步骤来进行开发。这为离线应用开发开启了新篇章。
45 0
|
5月前
|
开发框架 前端开发 .NET
C#编程与Web开发
【4月更文挑战第21天】本文探讨了C#在Web开发中的应用,包括使用ASP.NET框架、MVC模式、Web API和Entity Framework。C#作为.NET框架的主要语言,结合这些工具,能创建动态、高效的Web应用。实际案例涉及企业级应用、电子商务和社交媒体平台。尽管面临竞争和挑战,但C#在Web开发领域的前景将持续拓展。
171 3
|
5月前
|
SQL 开发框架 安全
C#编程与多线程处理
【4月更文挑战第21天】探索C#多线程处理,提升程序性能与响应性。了解C#中的Thread、Task类及Async/Await关键字,掌握线程同步与安全,实践并发计算、网络服务及UI优化。跟随未来发展趋势,利用C#打造高效应用。
182 3
|
16天前
|
API C#
C# 一分钟浅谈:文件系统编程
在软件开发中,文件系统操作至关重要。本文将带你快速掌握C#中文件系统编程的基础知识,涵盖基本概念、常见问题及解决方法。文章详细介绍了`System.IO`命名空间下的关键类库,并通过示例代码展示了路径处理、异常处理、并发访问等技巧,还提供了异步API和流压缩等高级技巧,帮助你写出更健壮的代码。
28 2