[C# 项目实战]: 制作一个备忘录(经典)

01

概述

     前几天群里有人问如何制作备忘录,感觉这样一个小实例挺适合新手们入门学习使用,所以就抽空做了出来。界面如下图:

d8bd04637b185259be2329174c3c9dbb.png

这个备忘录主要包括了如下功能:

① 备忘录信息的增、删、改、查;

② 备忘录时间到了以后进行语音播报。

功能很简单,但是要实现这么一个功能,也涉及众多的知识点,接下来详细进行分解。

02


内容详述

①界面button的图标:

90276fd08243c0911fdfbc41d9377550.png

图标图片可以上网上下载,下载好以后放到项目目录中,然后在项目中找到你的图片——>右键包括在项目中——>再右键,点击属性:

复制到输出目录,更改为始终复制。

生成操作,更改为内容。

ff23c86b4bda2589efbc8a3fbbc514ba.png

前台XMAL操作:

<Button Margin="15,5" MinWidth="60" cal:Message.Attach="[Event Click] = [Action SearchClick]" ><WrapPanel ><Image Source="/Images/search.png" Width="15" Height="15" /><TextBlock Text="查找" VerticalAlignment="Center" /></WrapPanel></Button>

② 数据源:这里我采用从xml读取并绑定到界面,界面如果有修改,在页面退出时进行数据保存,当然你也可以使用数据库去操作

XML文件位置:根目录的RawData下

dcee1094690b0c6828c8babc1dfbc713.png

XML文件数据内容如下:

06e8ac1cc6f19b5991342177b6752d0d.png

MemorandumModel数据模型定义:

public class MemorandumModel {public string Title { get; set; }public EvenType EvenType { get; set; }public DateTime DateTime { get; set; }public bool IsComplete { get; set; }}

③XML文件的读取和保存:MemorandumRealList是我们所有数据的集合,为了方便界面查询,界面绑定了MemorandumShowList 这个集合

xml读取:

public void XmlDocReader(){//XmlDocument读取xml文件XmlDocument xmlDoc = new XmlDocument();xmlDoc.Load(XmlDocPath);//获取xml根节点XmlNode xmlRoot = xmlDoc.DocumentElement;if (xmlRoot == null)return;//读取所有的节点foreach (XmlNode node in xmlRoot.SelectNodes("MemorandumModel")){MemorandumRealList.Add(new MemorandumModel(){Title = node.SelectSingleNode("Title").InnerText,EvenType = (EvenType)Enum.Parse(typeof(EvenType), node.SelectSingleNode("EvenType").InnerText),DateTime = Convert.ToDateTime(node.SelectSingleNode("DateTime").InnerText),IsComplete = Convert.ToBoolean(node.SelectSingleNode("IsComplete").InnerText)}); }MemorandumShowList = new  ObservableCollection<MemorandumModel>(MemorandumRealList);}

xml文件保存:

public void SaveXmlDoc(){//获取根节点对象XDocument document = new XDocument();XElement xmlRoot = new XElement("MemorandumModels");XElement memorandumModel;foreach (var memorandumReal in MemorandumRealList){memorandumModel = new XElement($"MemorandumModel");memorandumModel.SetElementValue("Title", memorandumReal.Title);memorandumModel.SetElementValue("EvenType", memorandumReal.EvenType);memorandumModel.SetElementValue("DateTime", memorandumReal.DateTime);memorandumModel.SetElementValue("IsComplete", memorandumReal.IsComplete);xmlRoot.Add(memorandumModel);}xmlRoot.Save(XmlDocPath);}

④查询:如果全选选中,则显示全部内容,未勾选,则采用link去匹配选中信息去筛选,我这里是所有信息去匹配的,你也可以自己修改下,去只匹配某一项或几项内容

public void SearchClick(){SaveXmlDoc();if (SelectAll){MemorandumShowList = new ObservableCollection<MemorandumModel>(MemorandumRealList);return;}MemorandumShowList = new ObservableCollection<MemorandumModel>(MemorandumRealList.Where(t => t.EvenType == EvenTypeList[SelectedIndex]).Where(s => s.IsComplete == IsCompleteStatus).Where(p => p.Title == TitleText).Where(x => x.DateTime == DateTime.Parse(DataTimeContext)) .ToList() );}

⑤标题栏未输入内容时显示灰色提示字体,有输入时输入内容显示黑色字体:

这里采用事件处理:获取到光标时

public void LostFocus(){if (string.IsNullOrEmpty(TitleText)){TitleText = "备忘录标题";TitleColor = Color.DimGray;}}

光标离开时:

public void GotFocus(){TitleText = "";TitleColor = Color.Black;}

⑥选中行删除:

public void DeleteClick(){MemorandumRealList.Remove(SelectedItem);MemorandumShowList.Remove(SelectedItem);}

⑦行号获取:在行选择改变事件中去做

public void GridControl_SelectedItemChanged(object sender, SelectedItemChangedEventArgs e){GridControl gd = sender as GridControl;SelectRow = gd.GetSelectedRowHandles()[0];//选中行的行号}

⑧添加信息:

public void Add(){MemorandumRealList.Add(new MemorandumModel(){Title = titleText,DateTime =DateTime.Parse(DataTimeContext),EvenType = EvenTypeList[SelectedIndex],IsComplete = IsCompleteStatus});MemorandumShowList.Add(new MemorandumModel(){Title = titleText,DateTime = DateTime.Parse(DataTimeContext),EvenType = EvenTypeList[SelectedIndex],IsComplete = IsCompleteStatus});}

⑨修改信息:

public void Modify(){MemorandumRealList[SelectRow] = new MemorandumModel(){Title = titleText,DateTime = DateTime.Parse(DataTimeContext),EvenType = EvenTypeList[SelectedIndex],IsComplete = IsCompleteStatus};MemorandumShowList[SelectRow] = new MemorandumModel(){Title = titleText,DateTime = DateTime.Parse(DataTimeContext),EvenType = EvenTypeList[SelectedIndex],IsComplete = IsCompleteStatus};}

⑩定时器查询:采用using System.Threading.Tasks;下的单线程定时器DispatcherTimer,

定义和初始化:

private DispatcherTimer timer;timer = new DispatcherTimer();timer.Interval = TimeSpan.FromMinutes(1);timer.Tick += timer1_Tick;timer.Start();

定时器事件:我这里每隔一分钟查询一次,查询到当前事件到了提醒时间就进行一次语音播报:

private void timer1_Tick(object sender, EventArgs e){foreach (var memorandum in MemorandumRealList){if(DateTime.Now >= memorandum.DateTime){SpeakAsync(memorandum.Title);}}}

⑩①:语音播报:这里开了task线程执行

/// <summary>/// 微软语音识别/// </summary>/// <param name="content">提示内容</param>public static void SpeakAsync(string content){try{Task.Run(() =>{SpVoice voice = new SpVoice();voice.Rate = 1;//速率[-10,10]voice.Volume = 10;//音量[0,100]voice.Voice = voice.GetVoices().Item(0);//语音库voice.Speak(content);});}catch (Exception ex){throw ex;}}

⑩② 界面时间处理:

  • 界面的表格采用的dev控件gridcontrol,默认情况下,时间只显示年月日,如果需要显示时分,需要设定:EditSettings如下

<dxg:GridColumn  Header="提醒时间" FieldName="DateTime" MinWidth="120" ><dxg:GridColumn.EditSettings><!--<xctk:DateEditSettings DisplayFormat="dd-MM-yyyy HH:mm:ss.fff"/>--><xctk:DateEditSettings DisplayFormat="yyyy-MM-dd HH:mm"/></dxg:GridColumn.EditSettings></dxg:GridColumn>

如果使用的是wpf 自带的表格控件datagrid,相对好处理

<DataGridTextColumn Header="提醒时间" Binding="{Binding Path=DateTime,StringFormat='yyyy年MM月dd日 HH:mm:ss'}" MinWidth="300" />
  • 界面顶端的时间控件采用:toolkit下的xctk1:DateTimeUpDown这个控件

    她绑定的是一个字符串类型的数据,所以添加时候,需要将他转换为datetime类型, DateTime.Parse(DataTimeContext),或者

     DateTime = Convert.ToDateTime(DataTimeContext)

    <xctk1:DateTimeUpDown x:Name="_minimum"  Format="Custom" FormatString="yyyy/MM/dd HH:mm" Text="{Binding DataTimeContext}" HorizontalAlignment="Left" VerticalAlignment="Center"Value="2016/01/01T12:00"  Margin="15,5"/>

⑩③combobox枚举内容绑定:

public ObservableCollection<EvenType> EvenTypeList { get; set; } = new ObservableCollection<EvenType>();
foreach (EvenType evenType in Enum.GetValues(typeof(EvenType))){EvenTypeList.Add(evenType);}

⑩④关于gridcontrol TableView 的常用属性介绍

TableView 的常用属性:AllowPerPixelScrolling //逐像素滚动;
AllowScrollAnimation //滚动动画,当下拉滚动条时有动画效果
NavigationStyle //选中方式是一行还是单元格
ShowIndicator //是否在每一行之前显示小方块
UseEvenRowBackground //隔行其背景颜色会有所区分
AllowScrollToFocusedRow //允许滚动到选中行
AllowResizing //允许调整尺寸
AllowSorting //允许排序
AutoWidth //允许自动调整列宽
AllowMoveColumnToDropArea //允许将一列拖到空白处进行分组
AllowGrouping //允许分组
AllowFilterEditor //允许显示过滤盘
AllowEditing //允许编辑
ShowGroupPanel//显示分组panel
ShowHorizontalLines   ShowVerticalLines //显示表格中每行每列垂直和水平线
IsColumnMenuEnabled //是否关闭右键列菜单

03


前台代码

直接上代码,比较简单,不展开讲解了:

<UserControlxmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:Caliburn.Micro.Hello"xmlns:cal="http://www.caliburnproject.org" xmlns:sys="clr-namespace:System;assembly=mscorlib"xmlns:dxg="http://schemas.devexpress.com/winfx/2008/xaml/grid" xmlns:xctk="http://schemas.devexpress.com/winfx/2008/xaml/editors" xmlns:xctk1="http://schemas.xceed.com/wpf/xaml/toolkit" x:Class="Caliburn.Micro.Hello.MemorandumView" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800" ><UserControl.Resources><local:FontColorConverter x:Key="FontColorConverter" /><Style TargetType="{x:Type TextBox}"><Setter Property="HorizontalContentAlignment" Value="Left"/><Setter Property="VerticalContentAlignment" Value="Center"/><Setter Property="Width" Value="100"/>
</Style><Style TargetType="{x:Type CheckBox}"><Setter Property="HorizontalAlignment" Value="Center"/><Setter Property="VerticalAlignment" Value="Center"/><Setter Property="Foreground" Value="Black"/>
</Style><Style TargetType="Button"><Setter Property="Foreground" Value="Black"/>
</Style><DataTemplate x:Key="rowIndicatorContentTemplate"><StackPanel VerticalAlignment="Stretch"HorizontalAlignment="Stretch"><TextBlock Text="{Binding RowHandle.Value}"TextAlignment="Center" Foreground="Black"/></StackPanel></DataTemplate></UserControl.Resources><StackPanel Orientation="Vertical"><StackPanel Orientation="Horizontal"><TextBox Text="{Binding TitleText}"  Margin="15,5" cal:Message.Attach="[Event GotFocus] = [Action GotFocus];[Event LostFocus] = [Action LostFocus]" Foreground="{Binding TitleColor, Converter={StaticResource FontColorConverter}}"/><ComboBox ItemsSource="{Binding EvenTypeList}" Margin="15,5"  SelectedIndex="{Binding SelectedIndex}" MinWidth="100" Foreground="Black"/><!--<DatePicker Text="{Binding DataTimeContext,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"SelectedDate="{x:Static sys:DateTime.Now}" HorizontalAlignment="Left" VerticalAlignment="Center" Margin="15,5"  />--><xctk1:DateTimeUpDown x:Name="_minimum"  Format="Custom" FormatString="yyyy/MM/dd HH:mm" Text="{Binding DataTimeContext}" HorizontalAlignment="Left" VerticalAlignment="Center"Value="2016/01/01T12:00"  Margin="15,5"/><CheckBox IsChecked="{Binding IsCompleteStatus}" Margin="15,5" Content="是否完成" Foreground="Black"/><Button Margin="15,5" MinWidth="60" cal:Message.Attach="[Event Click] = [Action SearchClick]" ><WrapPanel ><Image Source="/Images/search.png" Width="15" Height="15" /><TextBlock Text="查找" VerticalAlignment="Center" /></WrapPanel></Button></StackPanel><Border BorderBrush="LightBlue" CornerRadius="2" BorderThickness="2" ><dxg:GridControl AutoGenerateColumns="AddNew" EnableSmartColumnsGeneration="True"  AllowLiveDataShaping="True" cal:Message.Attach="[Event SelectedItemChanged] = [Action GridControl_SelectedItemChanged($source,$event)];" ItemsSource="{Binding MemorandumShowList}" SelectedItem="{Binding SelectedItem}" Height="330" Foreground="Black"><dxg:GridControl.View><dxg:TableView ShowTotalSummary="True" AllowMoveColumnToDropArea="False" AllowGrouping="False" AutoExpandOnDrag="False" ShowDragDropHint="False" ShowGroupPanel="False" AllowColumnMoving="False" AllowResizing="False" Foreground="Black"RowIndicatorContentTemplate="{StaticResource rowIndicatorContentTemplate}" /></dxg:GridControl.View><dxg:GridColumn  Header="标题" FieldName="Title"   MinWidth="100"/><dxg:GridColumn  Header="类型" FieldName="EvenType"  MinWidth="100"/><dxg:GridColumn  Header="提醒时间" FieldName="DateTime" MinWidth="120" ><dxg:GridColumn.EditSettings><!--<xctk:DateEditSettings DisplayFormat="dd-MM-yyyy HH:mm:ss.fff"/>--><xctk:DateEditSettings DisplayFormat="yyyy-MM-dd HH:mm"/></dxg:GridColumn.EditSettings></dxg:GridColumn><dxg:GridColumn  Header="状态" FieldName="IsComplete"  MinWidth="100"/></dxg:GridControl></Border><StackPanel Orientation="Horizontal"><CheckBox IsChecked="{Binding SelectAll}" Margin="35,5" Content="全选"/><Button Margin="35,5" MinWidth="60" cal:Message.Attach="[Event Click] = [Action DeleteClick]" ><WrapPanel ><Image Source="/Images/delete.png" Width="15" Height="15" /><TextBlock Text="删除" VerticalAlignment="Center" /></WrapPanel></Button><Button Margin="35,5" MinWidth="60" Name="Add"><WrapPanel ><Image Source="/Images/add.png" Width="15" Height="15" /><TextBlock Text="添加" VerticalAlignment="Center" /></WrapPanel></Button><Button Margin="35,5" MinWidth="60" Name="Modify"><WrapPanel ><Image Source="/Images/modify.png" Width="15" Height="15"/><TextBlock Text="修改" VerticalAlignment="Center" /></WrapPanel></Button></StackPanel></StackPanel>
</UserControl>

04


效果演示

4bdb51f2bf72454d34ca07d09e30dd98.gif

05


源码

源码下载 

链接:https://pan.baidu.com/s/1yExT_zXFfd6TiAJYoD8kIw 

提取码:在下面这个公众号对话框发送【备忘录

或者直接添加小编微信:mm1552923   获取。

技术群:添加小编微信并备注进群

小编微信:mm1552923   

公众号:dotNet编程大全      

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/291139.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RedHat 5.4下构建postfix全功能电子邮(七)-extmail extman平台-(下集)

2019独角兽企业重金招聘Python工程师标准>>> RedHat 5.4下构建postfix全功能电子邮&#xff08;七&#xff09;-extmail extman平台-&#xff08;下集&#xff09; 三、设置邮件系统的图形化日志信息 [rootmail ~]# ln -sf /usr/local/apache2/htdocs/extman/addon…

JNI中的内存管理(转)

源&#xff1a;JNI中的内存管理 JNI 编程简介 JNI&#xff0c;Java Native Interface&#xff0c;是 native code 的编程接口。JNI 使 Java 代码程序可以与 native code 交互——在 Java 程序中调用 native code&#xff1b;在 native code 中嵌入 Java 虚拟机调用 Java 的代码…

C# 异步方法的异常处理

在使用异步方法时&#xff0c;应该知道错误的一些特殊处理方式。所有 ErrorHandling 示例的代码都使用了如下名称空间&#xff1a;SystemSystem.Threading.Tasks从一个简单的方法开始&#xff0c;它在延迟后抛出一个异常&#xff1a;static async Task ThrowAfter(int ms, stri…

Mark Down 使用实例

为什么80%的码农都做不了架构师&#xff1f;>>> Mark Down 使用实例 MarkDown是一个非常轻量级的 【标记语言】&#xff0c;有点有很多&#xff0c;书写比较快速&#xff0c;学习成本低&#xff0c;统一的排版模式&#xff0c;可导出 PDF HTML 等文档格式&#xff…

JoySSL付费版证书的优势

JoySSL付费版证书相比免费版有很多优势。首先&#xff0c;付费版证书通常由权威的CA&#xff08;证书颁发机构&#xff09;签发&#xff0c;在浏览器和操作系统中具有99.99%的兼容性&#xff0c;被主流浏览器如Chrome、Firefox、Safari和Edge等广泛支持和认可。这确保了无论用户…

Git命令集十三——快照操作

2019独角兽企业重金招聘Python工程师标准>>> Git命令集十三——快照操作 Git工具中提供了一个stash命令&#xff0c;这个命令的作用是创建快照。快照主要的用途是将当前未更新到缓存区的修改进行入栈保存&#xff0c;创建快照后&#xff0c;Git的状态会变回上一次提…

Asp.net core IdentityServer4与传统基于角色的权限系统的集成

img写在前面因为最近在忙别的&#xff0c;好久没水文了 今天来水一篇&#xff1b;在学习或者做权限系统技术选型的过程中&#xff0c;经常有朋友有这样的疑问 &#xff1a;“IdentityServer4的能不能做到与传统基于角色的权限系统集成呢&#xff1f;”“我的公司有几百个接口&a…

算法小白——基本排序算法入门

计算的 时间复杂度&#xff08;最差、平均、和最好性能&#xff09;&#xff0c;依据列表&#xff08;list&#xff09;的大小(n)。一般而言&#xff0c;好的性能是O(n log n)&#xff0c;且坏的性能是O(n^2)。对于一个排序理想的性能是O(n)。仅使用一个抽象关键比较运算的排序…

使用Dynamic LINQ创建高级查询服务

前言在以前的文章中&#xff0c;我们介绍了使用AutoFilterer.Generators创建高级查询服务。但是&#xff0c;AutoFilterer.Generators只能提供简单的范围筛选&#xff1a;今天&#xff0c;我们介绍如何使用Dynamic LINQ轻松实现更强大的高级查询服务。Demo创建ASP.NET Core Web…

线程池的开源实现(mariadb和percona版本)

2019独角兽企业重金招聘Python工程师标准>>> 一、"Thread pool in MariaDB 5.5" 线程池解决的问题&#xff1a; 传统mysql使用一个线程处理一个客户端连接&#xff0c;如果许多的并发用户&#xff0c;将使性能下降。因为大量的线程将引起上下文交换&#…

C++之goto

1 goto code: result:

ABP vNext微服务架构详细教程——结束语

ABP vNext微服务架构详细教程——简介ABP vNext微服务架构详细教程——架构介绍ABP vNext微服务架构详细教程——身份管理服务ABP vNext微服务架构详细教程——基础服务层ABP vNext微服务架构详细教程——聚合服务ABP vNext微服务架构详细教程——身份认证服务ABP vNext微服务架…

创建 linux分区命令,Linux中创建分区

在很多情况下我们可能需要在使用Linux的时候创建新的分区来帮助我们更好的学习和工作&#xff0c;接下来我就详细的介绍一下如何利用fdisk这条命令进行硬盘分区。Linux磁盘分区和windows存在区别&#xff0c;Linux分区分为三类 主分区 扩展分区 和逻辑分区。然而它们三个关系有…

Android studio之Error:(23, 17) Failed to resolve: junit:junit:4.12

1 probleam 2 resolve method // testCompile junit:junit:4.12

20杨氏矩阵查找

问题描述&#xff1a;在一个m行n列二维数组中&#xff0c;每一行都按照从左到右递增的顺序排序&#xff0c;每一列都按照从上到下递增的顺序排序。请完成一个函数&#xff0c;输入这样的一个二维数组和一个整数&#xff0c;判断数组中是否含有该整数。 例如下面的二维数组就…

玩一玩微信公众号开发(一) 接入系统

一开始我准备学一学微信开发。后来看了一下文档&#xff0c;需要自己搭服务器进行接口对调。有点麻烦所以就没继续学下去。现在学习过了Kotlin、Spring Boot很多东西&#xff0c;感觉可以比较方便的进行开发了。今天就来回过头学习一下。 准备工作 申请公众号 首先说明一下&…

Android studio之NDK integration is deprecated in the current plugin解决办法

1 、问题 编译Android项目&#xff0c;出现下面错误 NDK integration is deprecated in the current plugin 2、解决办法 在我们 gradle.properties(Project Properties) file add android.useDeprecatedNdktrue

使用 System.Net.Http.Json 简化 HttpClient 的使用

使用 System.Net.Http.Json 简化 HttpClient 的使用Intro从 .NET Core 3.1 开始&#xff0c;微软添加了一个 System.Net.Http.Json 的扩展&#xff0c;可以用来简化 HttpClient 的使用&#xff0c;看到在很多项目里还并未开始使用&#xff0c;所以想向大家介绍一下SamplePostAs…

MySQL的四种不同查询的分析

1.前置条件&#xff1a;本次是基于小数据量&#xff0c;且数据块在一个页中的最理想情况进行分析&#xff0c;可能无具体的实际意义&#xff0c;但是可以借鉴到各种复杂条件下&#xff0c;因为原理是相同的,知小见大&#xff0c;见微知著&#xff01;打开语句分析并确认是否已经…

.NET6之MiniAPI(十八):OpenAPI swagger

从本篇开始&#xff0c;介绍一些很不错的三方库&#xff0c;来丰富MiniAPI的使用。在创建MiniAPI项目时&#xff0c;模板提供了一个是否启用OpenAPI的选项&#xff0c;足见这个三方库的优势和强大。OpenAPI为我们测试API提供了强大的支持&#xff0c;调用API的开发人员&#xf…