C#案例_WPF + XML 本地备忘录

版权声明:版权声明:本文为博主原创文章,转载请注明出处。 https://blog.csdn.net/shaotaiban1097/article/details/82723036

案例介绍

实现一个简单的备忘录程序,程序启动后,出现在桌面右上角(为了看上去更简洁,去掉了标题栏,并且去除了任务栏中的图标)

主要功能


1、双击打开后,可以在窗体中输入备忘录内容。双击可以改变文本的编辑状态(可编辑,不可编辑)
2、窗体加载时,去指定路径下查找指定的XML文档(用来存储备忘内容),如果存在,则加载最近一次节点的内容,如不存在,则不做操作
3、每次当窗体中文本发生改变时,触发定时器,5分钟之后自动保存,如期间手动保存,则终止计时。如未手动保存,则5分钟之后自动保存后终止计时器
4、监听窗体内按钮事件(注意并非全局按钮事件),Ctrl + S :保存; Ctrl + Q : 保存并退出
5、设置文本改变标识符,全局记录文本是否变化。文本若未改变,手动保存时不写入XML文档(避免多次Ctrl + S 手动保存造成XML文档中大量重复数据)
6、程序退出前自动保存最新文本记录

* 由于初学XML,所以尝试使用XML写了这个案例,仅为一次学习过程中的练习,不足之处望多指正!

WPF窗体主要代码

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="memoire" Height="360" Width="280" WindowStyle="None" ResizeMode="NoResize" Background="Cornsilk" Topmost="False" ShowInTaskbar="False"
        WindowStartupLocation="Manual" Loaded="Grid_Loaded_1" Closing="Window_Closing_1" MouseDoubleClick="rbox_1_MouseDoubleClick_1" KeyDown="Window_KeyDown_1">
    <Grid Margin="0,0,0,0">
        <RichTextBox HorizontalAlignment="Left" Margin="0,0,0,10" VerticalAlignment="Top" Background="Transparent" Name="rbox_1" MouseDoubleClick="rbox_1_MouseDoubleClick_1" TextChanged="rbox_1_TextChanged_1" FontFamily="楷体" FontSize="20" FontWeight="Bold">
            <FlowDocument>
                <Paragraph>
                    <Run Text=""/>
                </Paragraph>
            </FlowDocument>
        </RichTextBox>
        <!--<Button Content="" HorizontalAlignment="Left" Margin="270,350,0,0" Width="10" Name="btn_1" Click="btn_1_Click"/>-->
    </Grid>
</Window>

C#后台主要代码

using System;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Threading;
using System.Xml;

namespace WpfApplication1 {
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        //创建定时器对象
        DispatcherTimer dispatcherTimer = new DispatcherTimer();

        //定义全局标识区分文本是否发生改变  如未改变 则手动保存后不写入文档(避免手动多次control + S占用)
        bool isChange = false;

        public MainWindow()
        {
            InitializeComponent();
            dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
            dispatcherTimer.Interval = new TimeSpan(0, 0, 300);
            dispatcherTimer.IsEnabled = false;
        }

        /// <summary>
        /// 按钮点击事件 关闭窗口  暂时取消按钮(关闭窗口功能由 control + Q 完成)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_1_Click(object sender, RoutedEventArgs e)
        {
            Close();
        }

        /// <summary>
        /// 窗体加载时默认位置出现在桌面右上角  并加载上次关闭时的文本  默认文本状态为只读(双击改变为可编辑)
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Grid_Loaded_1(object sender, RoutedEventArgs e)
        {
            Left = SystemParameters.PrimaryScreenWidth - Width;
            Top = 0;// SystemParameters.PrimaryScreenHeight;

            ReadLineXML("memoire.xml");
            rbox_1.IsReadOnly = true;
            isChange = false;
        }

        /// <summary>
        /// 双击窗体或文本域 改变文本的只读状态
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void rbox_1_MouseDoubleClick_1(object sender, MouseButtonEventArgs e)
        {
            //rbox_1.Selection.ApplyPropertyValue(TextElement.ForegroundProperty, Brushes.Gray);
            rbox_1.IsReadOnly = rbox_1.IsReadOnly ? false : true;
        }

        /// <summary>
        /// 定时执行    文本发生改变时触发计时  
        ///     5分钟后如果未手动保存则触发自动保存 如手动保存或关闭程序则终止计时  自动保存触发后终止计时 下次文本改变后重新触发
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void dispatcherTimer_Tick(object sender, EventArgs e)
        {
            CreateXML();
            dispatcherTimer.Stop();
        }

        /// <summary>
        /// 新建/追加XML文档
        /// </summary>
        private void CreateXML()
        {
            if (!isChange) { return; }

            XmlDocument xml = new XmlDocument();

            //创建根节点对象
            XmlElement root;

            //新建或加载XML文件
            if (!File.Exists("memoire.xml"))
            {
                XmlDeclaration header = xml.CreateXmlDeclaration("1.0", "UTF-8", null);
                xml.AppendChild(header);
                root = xml.CreateElement("memoire");
                xml.AppendChild(root);
            }
            else
            {
                xml.Load("memoire.xml");
                root = xml.DocumentElement;
            }

            //momoireText节点的Index属性每次保存时自增 方便直接读取最新记录
            int index = 0;
            if (xml.SelectNodes("/memoire/momoireText").Count > 0)
            {
                index = xml.SelectNodes("/memoire/momoireText").Cast<XmlNode>().ToList().Select(p => int.Parse(p.Attributes["Index"].Value)).Max();
            }

            //创建momoireText节点 包含创建时间、序号两个属性  时间取系统时间  序号自动递增
            XmlElement memoireText = xml.CreateElement("momoireText");
            memoireText.SetAttribute("DateTime", DateTime.Now.ToString());
            memoireText.SetAttribute("Index", (++index).ToString());
            root.AppendChild(memoireText);

            //输入的文本逐行读取并保存
            TextRange tr = new TextRange(rbox_1.Document.ContentStart, rbox_1.Document.ContentEnd);
            string text = tr.Text;
            string[] items = text.Split("\r\n".ToArray(), StringSplitOptions.RemoveEmptyEntries);
            int seq = 0;

            foreach (var item in items)
            {
                XmlElement mItem = xml.CreateElement("mItems");
                mItem.SetAttribute("Seq", seq++.ToString());
                mItem.SetAttribute("Content", item);
                mItem.SetAttribute("Status", "1");

                memoireText.AppendChild(mItem);
            }

            xml.Save("memoire.xml");

            isChange = false;//默认首次加载时 因为要读取上次关闭之前的文档 isChange会变为true 所以需要在加载完成后将其重新置为false
        }

        /// <summary>
        /// 读取XML文档
        /// </summary>
        /// <param name="fileName"></param>
        private void ReadLineXML(string fileName)
        {
            XmlDocument xml = new XmlDocument();

            //加载XML文档
            if (!File.Exists("memoire.xml")) { return; }
            xml.Load(fileName);

            XmlElement root = xml.DocumentElement;//获取根节点


            //取Index值最大的momoireText节点中的所有子节点及其属性(即最新的一次保存记录)
            int index = xml.SelectNodes("/memoire/momoireText").Cast<XmlNode>().Select(p => int.Parse(p.Attributes["Index"].Value)).Max();
            XmlNodeList xnl = xml.SelectNodes("/memoire/momoireText[@Index='" + index.ToString() + "']/mItems");

            //读取XML文件 并加载
            foreach (XmlNode item in xnl)
            {
                //string text = item.Attributes["Seq"].InnerText;
                string value = item.Attributes["Content"].Value;
                rbox_1.AppendText(value + "\r\n");
            }

            //xml.RemoveAll();
        }

        /// <summary>
        /// 程序退出时 自动保存
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Window_Closing_1(object sender, System.ComponentModel.CancelEventArgs e)
        {
            CreateXML();
        }

        /// <summary>
        /// 键盘监听 按下control + Q 时 保存并退出  按下control + S 时 保存文本
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Window_KeyDown_1(object sender, KeyEventArgs e)
        {
            if (Keyboard.IsKeyDown(Key.LeftCtrl) && Keyboard.IsKeyDown(Key.Q))
            {
                Close();
            }
            if (Keyboard.IsKeyDown(Key.LeftCtrl) && Keyboard.IsKeyDown(Key.S))
            {
                CreateXML();
                dispatcherTimer.Stop();
            }
        }

        /// <summary>
        /// 每次文本内容改变时  开启定时器 5 分钟后自动保存
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void rbox_1_TextChanged_1(object sender, TextChangedEventArgs e)
        {
            isChange = true;
            dispatcherTimer.Start();
        }
    }
}

猜你喜欢

转载自blog.csdn.net/shaotaiban1097/article/details/82723036