c#

06
Feb
0

Json的序列化和反序列化

第一种:
//使用JavaScriptSerializer方式需要引入的命名空间,这个在程序集System.Web.Extensions.dll.中
using System.Web.Script.Serialization;

region 2.JavaScriptSerializer方式实现序列化和反序列化

        Student stu = new Student()
           {
               ID = 1,
               Name = "关羽",
               Age = 2000,
               Sex = "男"
           };

        JavaScriptSerializer js = new JavaScriptSerializer();
        string jsonData = js.Serialize(stu);//序列化
        Console.WriteLine(jsonData);
        ////反序列化方式一:
        string desJson = jsonData;
        //Student model = js.Deserialize<Student>(desJson);// //反序列化
        //string message = string.Format("ID={0},Name={1},Age={2},Sex={3}", model.ID, model.Name, model.Age, model.Sex);
        //Console.WriteLine(message);
        //Console.ReadKey(); 
        ////反序列化方式2
        dynamic modelDy = js.Deserialize<dynamic>(desJson); //反序列化
        string messageDy = string.Format("动态的反序列化,ID={0},Name={1},Age={2},Sex={3}",
            modelDy["ID"], modelDy["Name"], modelDy["Age"], modelDy["Sex"]);//这里要使用索引取值,不能使用对象.属性
        Console.WriteLine(messageDy);
        Console.ReadKey(); 
        #endregion

第二种:
//使用DataContractJsonSerializer方式需要引入的命名空间,在System.Runtime.Serialization.dll.中
using System.Runtime.Serialization.Json;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.Serialization;

namespace JsonSerializerAndDeSerializer
{

[DataContract]

public class Student

{
    [DataMember]
   public int ID { get; set; }

    [DataMember]
   public string Name { get; set; }

    [DataMember]
   public int Age { get; set; }

    [DataMember]
   public string Sex { get; set; }
}

}

注意:上面的Student实体中的契约 [DataMember],[DataContract],是使用DataContractJsonSerializer序列化和反序列化必须要加的,对于其他两种方式不必加,也可以的

region 1.DataContractJsonSerializer方式序列化和反序列化

        Student stu = new Student()
         {
             ID = 1,
             Name = "曹操",
             Sex = "男",
             Age = 1000
         };
        //序列化
        DataContractJsonSerializer js = new DataContractJsonSerializer(typeof(Student));
        MemoryStream msObj = new MemoryStream();
        //将序列化之后的Json格式数据写入流中
        js.WriteObject(msObj, stu);
        msObj.Position = 0;
        //从0这个位置开始读取流中的数据
        StreamReader sr = new StreamReader(msObj, Encoding.UTF8);
        string json = sr.ReadToEnd();
        sr.Close();
        msObj.Close();
        Console.WriteLine(json);
        //反序列化
        string toDes = json;
        //string to = "{\"ID\":\"1\",\"Name\":\"曹操\",\"Sex\":\"男\",\"Age\":\"1230\"}";
        using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(toDes)))
        {
            DataContractJsonSerializer deseralizer = new DataContractJsonSerializer(typeof(Student));
            Student model = (Student)deseralizer.ReadObject(ms);// //反序列化ReadObject
            Console.WriteLine("ID=" + model.ID);
            Console.WriteLine("Name=" + model.Name);
            Console.WriteLine("Age=" + model.Age);
            Console.WriteLine("Sex=" + model.Sex);
        }
        Console.ReadKey(); 
        #endregion

第三种:
In Visual Studio, go to Tools Menu -> Choose Library Package Manger -> Package Manager Console. It opens a command window where we need to put the following command to install Newtonsoft.Json.

Install-Package Newtonsoft.Json
OR
In Visual Studio, Tools menu -> Manage Nuget Package Manger Solution and type “JSON.NET” to search it online. Here's the figure

//使用Json.NET类库需要引入的命名空间
//-----------------------------------------------------------------------------
using Newtonsoft.Json;
//-------------------------------------------------------------------------

region 3.Json.NET序列化

        List<Student> lstStuModel = new List<Student>() 
        {
        
        new Student(){ID=1,Name="张飞",Age=250,Sex="男"},
        new Student(){ID=2,Name="潘金莲",Age=300,Sex="女"}
        };

        //Json.NET序列化
        string jsonData = JsonConvert.SerializeObject(lstStuModel);

        Console.WriteLine(jsonData);
        Console.ReadKey();
        //Json.NET反序列化
        string json = @"{ 'Name':'C#','Age':'3000','ID':'1','Sex':'女'}";
        Student descJsonStu = JsonConvert.DeserializeObject<Student>(json);//反序列化
        Console.WriteLine(string.Format("反序列化: ID={0},Name={1},Sex={2},Sex={3}", descJsonStu.ID, descJsonStu.Name, descJsonStu.Age, descJsonStu.Sex));
        Console.ReadKey(); 
        #endregion
11
Nov
0

wpf 按键接收事件中的key值转换

wpf中的Key值和win32中的KEY不一样

原型
system.windows.input.key

win32 key是ascii
相互转换方法

KeyInterop.KeyFromVirtualKey
KeyInterop.VirtualKeyFromKey

还有一个转换类KeyConverter 原型:
system.windows.input.KeyConverter

11
Nov
0

WPF和WindowsForm下的按下Enter跳转下一个控件通用方法

WP下按下回车(enter)跳转下一个控件

protected override void OnKeyDown(KeyEventArgs e)
    {

        if (e.Key == Key.Enter)
        {
            // MoveFocus takes a TraveralReqest as its argument.
            TraversalRequest request = new TraversalRequest(FocusNavigationDirection.Next);

            // Gets the element with keyboard focus.
            UIElement elementWithFocus = Keyboard.FocusedElement as UIElement;

            // Change keyboard focus.
            if (elementWithFocus != null)
            {
                elementWithFocus.MoveFocus(request);
            }
            e.Handled = true;
        }
        base.OnKeyDown(e);
    }

WindowsForm下的按下回车(Enter)跳转到下一个控
/// <summary>

    /// 方法一:实现按下回车跳到下一个控件(不论是什么控件,如果需要可以在里面加上对控件类型的判断)
    /// </summary>
    /// <param name="e"></param>
    protected override void OnKeyDown(KeyEventArgs e)
    {

        if (e.KeyCode == Keys.Enter)
        {
            int i = 0;
            foreach (Control c in this.Controls)
            {
                if (c.Focused)
                {
                    i = c.TabIndex;
                    break;
                }
            }
            foreach (Control c in this.Controls)
            {
                if (c.TabIndex == (i + 1))
                {
                    c.Focus();
                    break;
                }
            }

        }
    }
    /// <summary>
    /// 方法二:灵活方便,可以通过方法中的参数控制是否要进入控件的子控件中,是否忽略tobstop的设置。
    /// </summary>
    /// <param name="e"></param>
    protected override void OnKeyPress(KeyPressEventArgs e)
    {
        //base.OnKeyPress(e);
        if (e.KeyChar == (char)13)
        {
            e.Handled = true;
            this.SelectNextControl(this.ActiveControl, true, true, true, false);
        }
    }
    /// <summary>
    /// 方法三:直接将enter按键转化为tab按键
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void Form1_KeyDown(object sender, KeyEventArgs e)
    {
        MessageBox.Show("");
        if (e.KeyCode == Keys.Enter)
        {
            SendKeys.Send("{TAB}");
            e.Handled = true;
        }
    }
10
Nov
0

.net强制退出主窗口的方法

.net类库已经帮助我们实现了窗口的关闭,如果此窗口是系统的主窗口,关闭此窗口即应该退出了整个应用程序。
但事实上有时候并不是这样的,关闭窗口,只是停止了当前窗口的消息循环。
系统主窗口,实质上是Main函数中开始消息循环的窗口,这个消息循环结束后,Main函数就基本上完成了历史使命,整个应用程序自然就结束了。
Application.Exit()方法是终止所有线程上的消息循环,一般情况下,无论在什么地方调用此方法,程序就能退出。
但是如果你在程序中加入了某些耗时甚至是死循环的线程,那么即使是消息循环终止,程序也依然不会结束。
比较温和比较合适的做法是结束消息循环之前,终止所有自己新建的线程。
有时候我们连自己也搞不清楚到底是那些顽固的线程在执行,就需要用点暴力的手段了。.net为我们提供了Environment.Exit(0)方法,调用此方法,应用程序即强制退出。

当你打开一个子窗体,进行某项操作时,如果字窗体中有循环操作时。如果运行中我关闭子窗体,发现窗体虽然关闭了,但子窗体中的循环程序却没有退出,一直在 执行,并占用着系统资源,直到循环结束,才真正的释放资源。尽管你在字窗体的Closed事件中写了如下代码:

  
  private void frmFileDisposal_Closed(object sender, System.EventArgs e)
 {
     this.Dispose();
     this.Close();
 }

从查MSDN和从网上查资料可以知道,Dispose()方法,虽然能释放当前窗体的资源,却不能强制结束循环,
要想强制突出当前程序要用:System.Environment.Exit(int exitcode)方法;该方法:终止当前进程并为基础操作系统提供指定的退出代码。

如下则问题解决:
private void frmFileDisposal_Closed(object sender, System.EventArgs e)

 {         
     System.Environment.Exit(System.Environment.ExitCode);   
     this.Dispose();
     this.Close();
 }

或者把它放到事件里:
while (MessageBox.Show("退出当前窗体?", "", MessageBoxButtons.YesNo) == DialogResult.No)

{
   for(int j=1; j<=i; j++) 
  {
      listBox1.Items.Add(j);
   }       

}
System.Environment.Exit(System.Environment.ExitCode);

还有一种方法: System.Threading.Thread.CurrentThread.Abort();

                      或者          Process.GetCurrentProcess().Kill() 
                       或者        Application.ExitThread();
                       或者        Application.ExitThread()

不过以上方法,都是强制直接退出了整个程序,不只是关闭子窗体。可能还会引发某些问题,
我感觉最好方法的就是,在子窗体的Closing事件中,写循环退出条件,这样就可以避免某些未知的错误,而且可以只关闭子窗体,并释放子窗体占用的资源

Application.Exit(); 方法停止在所有线程上运行的所有消息循环,并关闭应用程序的所有窗口

Application.Exit 是一种强行退出方式,就像 Win32 的 PostQuitMessage()。它意味着放弃所有消息泵,展开调用堆栈,并将执行返回给系统。

在 Windows(Win32 或 .NET)中关闭应用程序的正确方式是关闭它的主应用程序窗口(例如 Form.Close)。主消息泵结束后依然存在的任何窗口都需要手动关闭。在应用程序退出之前通过调用 Form.Close 或 Form.Dispose 来关闭窗口是清除窗口的良好做法,但这需要您有意识地去做。我们需要记住,.NET Framework 的 OnClosing() 是 Win32 的托管版本的 WM_CLOSE,而非 WM_DESTROY。

另外,如果您使用 form.Close(),通过处理 OnClosing 或 OnClosed 事件,就可以让您的应用程序清理内容、关闭文件等。如果您通过 Application.Exit 强行退出应用程序,就无法调用这些事件。

18
Sep
0

WPF MVVM 事件绑定

在使用MVVM时经常用到Command,鼠标双击,单击都可用Command绑上

把事件绑定到Command上通常有3种:

1.使用MouseBinding

2.引用System.Windows.Interactivity.dll(必须装了Blend才有该组件),使用触发器来绑定

3.使用CommandBehavior附加属性绑定(需下载CommandBehavior源码)

下面来看看这3种方法的优劣

0.png

使用MouseBinding:

WPF MVVM 事件绑定 - 唐 - Doncle
但是MouseAction只有这些成员:
WPF MVVM 事件绑定 - 唐 - Doncle
事件成员很基本,但是在实际应用上算少的了 ,而且不能在样式(Setter)上使用

使用触发器
1.png
使用前加命名空间 xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

WPF MVVM 事件绑定 - 唐 - Doncle
虽然可以使用EventName指定事件,所有事件都能涵括到,但是也不能在样式上使用

使用CommandBehavior

WPF MVVM 事件绑定 - 唐 - Doncle
这种方法通过使用附加属性、反射及动态方法,劣势当然是效率低啦

6599280884540231168.png

CommandBehavior源码摘自:AttachedCommandBehavior aka ACB

AttachedCommandBehavior.zip

关于集合的绑定:AttachedCommandBehavior V2 aka ACB

AttachedCommandBehavior v2.0.zip!