WinForm教程(一)App.config等配置文件

2023-11-06

最近又回到用WinForm开发项目,难免少不了跟数据库打交道。平时也会在App.config中写连接字串,但没有仔细深究过,当然除了写数据库字串,肯定还能写别的,我们无论在控制台程序还是窗体程序,都会遇见他,乘代码敲累之际,写篇博客平缓下。

应用程序配置文件是标准的 XML 文件,XML 标记和属性是区分大小写的。它是按需更改,开发人员可以使用配置文件来更改设置,而不必重编译应用程序。配置文件又分:(1)内置配置文件(2)用户自定义配置文件。内置配置文件主要包括App.config、Web.config、Settings.settings( 这个用的不多,操作也很简单,在此不详细叙述)等等。用户自定义配置文件一般是将配置信息放到XML文件或注册表中,配置信息一般包括程序设置,记录运行信息,保存控件的信息(比如位置,样式)。

(一)App.config

一般新建项目都会自动添加配置文件,如果没有可以选中项目,右击添加新建项,选择" 添加应用程序配置文件",即可完成添加,其根节点是固定的configuration。

常用的子节点有:connectionStrings、appSettings、configSections等,操作都略有不同。DotNet直接提供了操作各节点的后台方法,在用到ConfigurationManager时注意要添加System.Configuration.dll程序集的引用。通过下面程序例子,我们会有大致了解。

(1)connectionStrings

一般存放数据库连接字串,如开头所讲,注意后台获取方法。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>  
    <connectionStrings >
        <add name="MystrCon" connectionString="Server=58.210.75.190;Database=jkpt00003;User Id=root;Password=123456;Persist Security Info=True"/>
    </connectionStrings >
</configuration>

//不适用于配置节新增子元素
public static string conStr = System.Configuration.ConfigurationManager.ConnectionStrings["MystrCon"].ConnectionString;//后台获取方法

如果我们进行此connectionStrings节的增删改呢?首先不能通过上述后台ConfigurationManager方法直接赋值写入,会报错该配置是只读的。但肯定有别的方法进行完成诉求,通过Configuration配置对象来实现,请看下面程序。

Configuration config = System.Configuration.ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);        
config.ConnectionStrings.ConnectionStrings["suny"].ConnectionString = "is a suny?";//修改 
config.ConnectionStrings.ConnectionStrings.Add(new ConnectionStringSettings("cloudy", "is cloud"));//增加
//原始或新加子元素都能获取
string name_three = config.ConnectionStrings.ConnectionStrings["cloudy"].ToString();
config.Save(ConfigurationSaveMode.Modified);//只有加保存功能,*.vshost.exe.Config才会作改变
ConfigurationManager.RefreshSection("ConnectionStrings");

(2)appSettings

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings>
      <add key="connectionstring" value="Data Source=127.0.0.1;initial catalog=Guest;User ID =sa;password=eric19897222008 "/>
    </appSettings>
</configuration>
//private static string SQL_CONN_STR = System.Configuration.ConfigurationSettings.AppSettings["connectionstring"];//已经被废弃
//不能获取配直节新增子元素
private static string SQL_CONN_STR = System.Configuration.ConfigurationManager.AppSettings["connectionstring"];

注意:现在.Net FrameWork 2.0以上框架中已经明确表示此ConfigurationSettings属性已经废弃,建议改为 ConfigurationManager。

当然,也能像connectionStrings一样,也能进行增删改查,请看下面程序。

Configuration config = System.Configuration.ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
config.AppSettings.Settings["foggy"].Value = "is a fog?";//修改子节点
config.AppSettings.Settings.Remove("welcome");//删除子节点              
config.AppSettings.Settings.Add("url", "http://www.fx163.net");//增加子节点        
string get_ui = config.AppSettings.Settings["url"].Value;//获取子节点值,原配置或代码添加配置节子节点都适用   
config.Save(ConfigurationSaveMode.Modified);//只有加保存功能,*.vshost.exe.Config才会作改变
System.Configuration.ConfigurationManager.RefreshSection("AppSettings");

(3)configSections(自定义节点)

显然,用上面的两种默认的配置节,能满足基本使用。是否可以自定义配置节呢?当然可以了,我们可以自己定义各元素之间的关系,先看个简单的。

<configuration>
   <configSections>
      <section name="simple"  type="Appconfig.SimpleSection,Appconfig"/>
   </configSections>
   <simple maxValue="20" minValue="1"></simple>
   <startup> 
      <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
   </startup>
</configuration>

Xml文件,注意三个点,一是configSections配置节,自定义的一定要写在其外面;二是name是新增节名字,Type是程序集命名空间+类名和空间;三是是必须作为第一个配置节,否则无法获取配置对象实例,前面搞定,我们敲开后台大门,先定义一个配置类。

一般需要做如下三件事:
1. 定义类型从System.Configuration.ConfigurationSection继承;
2. 定义配置类的属性,这些属性需要用ConfigurationProperty特性修饰,并制定属性在配置节中的名称和其他一些限制信息;
3. 通过基类的string索引器实现属性的get ,set;

//新加了个.cs类文件
namespace Appconfig
{
 
    public class SimpleSection : System.Configuration.ConfigurationSection
    {
        [ConfigurationProperty("maxValue", IsRequired = false, DefaultValue = Int32.MaxValue)]
        public int MaxValue
        {
            get
            {
                return (int)base["maxValue"];
            }
            set
            {
                base["maxValue"] = value;
            }
         }
         [ConfigurationProperty("minValue", IsRequired = false, DefaultValue = 1)]
         public int MinValue
            {
                get { return (int)base["minValue"]; }
                set { base["minValue"] = value; }
            }
         [ConfigurationProperty("enabled", IsRequired = false, DefaultValue = true)]
         public bool Enable
         {
             get
             {
                 return (bool)base["enabled"];
             }
             set
             {
                 base["enabled"] = value;
             }
          }
     }
}
//获取配置信息代码
Appconfig.SimpleSection simple = ConfigurationManager.GetSection("simple") as Appconfig.SimpleSection;
MessageBox.Show(simple.MinValue.ToString() + simple.MaxValue.ToString());

我们看个再复杂点的,配置节点自带属性值和子元素:

<configuration>
   <configSections>
      <section  name="complex"  type="Appconfig.ComplexSection,Appconfig"/>
   </configSections>
   <complex height="190">
      <child firstName="James" lastName="Bond"/>
   </complex>
   <startup> 
      <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
   </startup>
</configuration>

这个配置的名字是complex,他有一个属性height,他的节点内还有一个child元素这个元素有两个属性firstName和lastName;对于这个内嵌的节点该如何实现呢?首先我们需要定义一个类,要从ConfigurationElement类继承,然后再用和SimpleSection类似的方法定义一些用ConfigurationProperty特性修饰的属性就可以了,当然属性值的get,set也要使用基类的索引器。如下实现:

namespace Appconfig
{
    class ComplexSection : ConfigurationSection 
    {
        [ConfigurationProperty("height", IsRequired = true)] 
        public int Height 
        { 
            get
            { 
                return (int)base["height"]; 
            } 
            set
            { 
                base["height"] = value; 
            } 
         } 
        [ConfigurationProperty("child", IsDefaultCollection = false)] 
        public ChildSection Child 
        { 
            get
            { 
                return (ChildSection)base["child"]; 
            } 
            set
            { 
                base["child"] = value; 
            } 
         } 
     }
    public class ChildSection : ConfigurationElement
    {
        [ConfigurationProperty("firstName", IsRequired = true, IsKey = true)]
        public string FirstName
        {
            get
            {
                return (string)base["firstName"];
            }
            set
            {
                base["firstName"] = value;
            }
        }

        [ConfigurationProperty("lastName", IsRequired = true)]
        public string LastName
        {
            get
            {
                return (string)base["lastName"];
            }
            set
            {
                base["lastName"] = value;
            }
        }
    }
}
 ComplexSection complex = ConfigurationManager.GetSection("complex") as ComplexSection;
 MessageBox.Show("Height" + complex.Height);
 MessageBox.Show("complex firstname+lastname:" + complex.Child.FirstName + complex.Child.LastName);

还有稍微再复杂一点的情况,我们可能要在配置中配置一组相同类型的节点,也就是一组节点的集合。如下面的配置:

<configuration>
  <configSections>
    <section name="morecomplex" type="Appconfig.MoreComplexSection,Appconfig"/>
  </configSections>
  <morecomplex height="190">
    <child firstName="James" lastName="Bond"/>
    <children>
      <add firstName="Zhao" lastName="yukai"/>
      <add firstName="Lee" lastName="yukai"/>
      <remove firstName="Zhao"/>
    </children>
  </morecomplex>
 <startup> 
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
 </startup>
</configuration>

请看children节点,它就是一个集合类,在它里面定义了一组add元素(children不是直接'/'结尾,包含两个子元素,见形式),也可以有remove节点把已经添进去的配置去掉。要使用自定义节点集合需要从ConfigurationElementCollection类继承一个自定义类,然后要实现此类GetElementKey(ConfigurationElement element)和ConfigurationElement CreateNewElement()两个方法;为了方便的访问子节点可以在这个类里面定义只读的索引器,请看下面的实现:

namespace Appconfig
{
    class MoreComplexSection : ConfigurationSection 
    {
        [ConfigurationProperty("height", IsRequired = true)]
        public int Height
        {
            get
            {
                return (int)base["height"];
            }
            set
            {
                base["height"] = value;
            }
        }
        [ConfigurationProperty("child", IsDefaultCollection = false)]
        public ChildSection Child
        {
            get
            {
                return (ChildSection)base["child"];
            }
            set
            {
                base["child"] = value;
            }
        }
        [ConfigurationProperty("children", IsDefaultCollection = false)]
        //[ConfigurationCollection(typeof(ChildSection), CollectionType = ConfigurationElementCollectionType.AddRemoveClearMap, RemoveItemName = "remove")]//可加可不加
        public Children Children
        {
            get
            {
                return (Children)base["children"];
            }
            set
            {
                base["children"] = value;
            }
        }
    }
    public class Children : ConfigurationElementCollection
    {
        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((ChildSection)element).FirstName;//新建节点定义一个Key值,Key同为firstname
        }

        protected override ConfigurationElement CreateNewElement()
        {
            return new ChildSection();
        }

        public ChildSection this[int i]
        {
            get
            {
                return (ChildSection)base.BaseGet(i);
            }
        }

        public ChildSection this[string key]
        {
            get
            {
                return (ChildSection)base.BaseGet(key);
            }
        }
        protected override string ElementName
        {
            get
            {
                return "children";
            }
        }
    }
    public class ChildSection : ConfigurationElement
    {
        [ConfigurationProperty("firstName", IsRequired = true, IsKey = true)]
        public string FirstName
        {
            get
            {
                return (string)base["firstName"];
            }
            set
            {
                base["firstName"] = value;
            }
        }

        [ConfigurationProperty("lastName", IsRequired = true)]
        public string LastName
        {
            get
            {
                return (string)base["lastName"];
            }
            set
            {
                base["lastName"] = value;
            }
        }
    }
}
MoreComplexSection morecomplex = ConfigurationManager.GetSection("morecomplex") as MoreComplexSection;
MessageBox.Show("Height" + morecomplex.Height);
MessageBox.Show("morecomplex child: firstname+lastname:" + morecomplex.Child.FirstName + morecomplex.Child.LastName);
//remove一个元素,所以只有1个
//组元素请参考 https://blog.csdn.net/sweety820/article/details/41695335
MessageBox.Show("morecomplex children: firstname+lastname:" + morecomplex.Children[0].FirstName + morecomplex.Children[0].LastName);

其实网上有很多微软提供的默认接口,如System.Configuration.DictionarySectionHandler、NameValueSectionHandler、SingleTagSectionHandler,去实现单或组元素获取,只需要写类去实现这些接口(Type用的是即是此类),很快就能获取到数据,可见https://blog.csdn.net/lulu_jiang/article/details/6688078https://www.cnblogs.com/caoyc/p/6002702.html两篇博客。当然现在我们用的是非继承接口自定义类,幸运的是,我们也实现了(单/组)元素的获取,前提代码量不小。如果使用系统标准的<add name=" ...", valeu="...">,就可以大大减少我们自定义的代码量,看下面程序:

<configuration>
  <configSections>
    <section name="easy" type="Appconfig.EasySection,Appconfig"/>
  </configSections>
  <easy height="190">
    <NVs>
      <add name="abc" value="123"/>
      <add name="abcd" value="12d3"/>
    </NVs>
  </esay>
 <startup> 
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
 </startup>
</configuration>
namespace Appconfig
{
    class EasySection : ConfigurationSection 
    {
        [ConfigurationProperty("height", IsRequired = true)]
        public int Height
        {
            get
            {
                return (int)base["height"];
            }
            set
            {
                base["height"] = value;
            }
        }
        [ConfigurationProperty("NVs", IsDefaultCollection = false)]
        public System.Configuration.NameValueConfigurationCollection NVs
        {
            get
            {
                return (NameValueConfigurationCollection)base["NVs"];
            }
            set
            {
                base["NVs"] = value;
            }
        }
    }
}
EasySection Easy= ConfigurationManager.GetSection("easy") as EasySection;
MessageBox.Show("Height" + Easy.Height);
MessageBox.Show(Easy.NVs["abc"].Value);

是不是代码量少了许多?上述基本上可以满足所有的配置需求了。不过还有一点更大但是不复杂的概念,就是sectionGroup。我们可以自定义SectionGroup,然后在sectionGroup中配置多个section;分组对于大的应用程序是很有意义的。如下配置,配置了一个包含simple和一个morecomplex两个section的sectionGroup

<configuration>
  <configSections>
    <sectionGroup type="Appconfig.SampleSectionGroup,Appconfig" name="sampleGroup">
      <section type="Appconfig.SimpleSection,Appconfig" allowDefinition="Everywhere" name="simple" />
      <section type="Appconfig.MoreComplexSection,Appconfig" allowDefinition="Everywhere" name="morecomplex"/>
    </sectionGroup>
  </configSections>
  <sampleGroup>
    <simple maxValue="20" minValue="1">
    </simple>
    <morecomplex height="190">
      <child firstName="James" lastName="Bond"/>
      <children>
        <add firstName="Zhao" lastName="yukai"/>
        <add firstName="Lee" lastName="yukai"/>
        <remove firstName="Zhao"/>
      </children>   
    </morecomplex>
  </sampleGroup>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </startup>
</configuration>
namespace Appconfig
{
    class SampleSectionGroup: System.Configuration.ConfigurationSectionGroup 
    {
        public MoreComplexSection Complex
        {
            get
            {
                return (MoreComplexSection)base.Sections["morecomplex"];
            }
        }

        public SimpleSection Simple
        {
            get
            {
                return (SimpleSection)base.Sections["simple"];
            }
        } 
    }
}

SimpleSection和MoreComplexSection不变,SectionGroup只是做个集合,需要注意的是SectionGroup不能使用如下方法获取ConfigurationManager.GetSection(string),要获得sectionGroup必须通过Configuration类的SectionGroups[string]索引器获得,如下示例代码:

SampleSectionGroup sample = (SampleSectionGroup)ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None).SectionGroups["sampleGroup"];
MessageBox.Show(sample.Simple.MinValue.ToString());
MessageBox.Show(sample.Complex.Children[0].LastName);

(二)Web.config

Web.config跟App.config差不多,由于我不了解C#的Web运用,所以没法举例。日后如果学习了这部分做网页知识,肯定会来补上。但是,个人觉得做网页并非是微软系C#的强项,更不提主流开发语言了。

(三)Settings.settings

简而言之,Settings对应App.config中的这两个Section:"configuration-userSettings"与"configuration-applicationSettings",Settings提供了可视化修改App.config中这两个Section的途径,然而Settings与App.config却是独立存在于磁盘上的两个实体。一般情况下,Settings可视化修改,App.config自动修改;反之,App.config修改,会询问Settings可视化是否同步,可同步亦可不同步(没意义),Properties.Settings.Default取值源都是App.config。

Setting有4个属性Name(命名),Type(类型),Value(值)和Scope(作用域),前面三个不难理解,重点讲一下Scope属性。Scope属性有两个值Application,User。这两者区别,简单来说,用户作用域设置在运行时为读/写,并且可在代码中对其值进行更改和保存。应用程序作用域设置在运行时为只读。虽然可以读取,但是不能对其进行写入。具有应用程序作用域的设置只能在设计时或通过手动修设置文件进行更改。

//father的scope为用户,son为程序
//Properties.Settings.Default.daughter = 17;//应用程序作用域设置在运行时为只读,会报错
//Properties.Settings.Default.son = "xiaoliu";
MessageBox.Show(Properties.Settings.Default.father);//用户程序作用域可读
Properties.Settings.Default.father = "liu";//用户程序作用域可写
//Properties.Settings.Default.Save();
MessageBox.Show(Properties.Settings.Default.father);

上面程序是基本的读写操作,我们重点来说说程序运行到Properties.Settings.Default.Save()这个函数。应用程序作用域总是从App.config读取,在程序中也不能修改,所以改动只要改App.config或者Settings.settings可视化修改,但用户作用域就比较麻烦了。范围为"用户"的属性 Settings 在第一次运行时会读取App.config里的初始值(系统里找不到),放入内存(可修改),但是一旦调用Save方法后,Settings里"用户"范围的属性就会保存在系统里面,类似WebForm里的Cookies一样,从此以后,读取都会从系统里保存的值里读取,手工修改App.config里的"用户"范围的属性不会影响到这些属性,但是在调用Reset方法时会从新从App.config里获取"用户"范围的属性写入到系统中 ,也就是说,settings里"用户"范围的属性总共有3个地方存储。

1、App.config配置文件——程序第一次运行,之前程序未调用save(),在系统中找不到就会从这里获取;

2、操作系统——当Settings调用save()保存后;

3、内存——程序启动后,实例化settings对象,该实例在创建的时候从系统(如果系统中没有就如前面提到的从配置文件中获取)读取在内存中(过渡作用);

确实我们会发现,一旦保存之后,无论修改哪里,都会读取的是保存的那个值。不过,可以使用方法让App.config、系统、内存这3个位置之间值的关系互相影响。

new() 构造函数,"用户"属性先检查系统,如果没有值,再从配置文件中读取到内存。

Properties.Settings setting = new Properties.Settings();
MessageBox.Show(setting.father);

Save(),将Settings"用户”范围的属性写入到系统中, settings实例后,在程序中被赋予新值,如果想保存这些值以便在程序下一次运行时使用,就可以调用Save保存。无论是new()对象还是Properties.Settings.Default.xx获取,程序运行都是内存取值,内存首选系统,最后App.Config。

Reload(),从系统或App.config中读取已保存的值刷新当前内存里"用户"范围的属性。先检查系统,当系统中没有保存时再从App.config中获取。

private void button1_Click(object sender, EventArgs e)
{              
    Properties.Settings.Default.father = "yes";
    Properties.Settings.Default.Save();            
    Properties.Settings.Default.father = "st";
    //Properties.Settings.Default.Reload();//这句加和不加出现完全不同结果
    Properties.Settings setting = new Properties.Settings();
    MessageBox.Show(Properties.Settings.Default.father);
    MessageBox.Show(Properties.Settings.Default.father);
}

Reset(),清空系统中保存的Settings,并且把App.config中对应属性存入系统中。

//App.config
<userSettings>
    <settings.Properties.Settings>     
        <setting name="father" serializeAs="String">
            <value>sun</value>
        </setting>
    </settings.Properties.Settings>
</userSettings>
private void button1_Click(object sender, EventArgs e)
{              
     Properties.Settings.Default.father = "yes";
     Properties.Settings.Default.Save();           
     //Properties.Settings.Default.Reset();//这句加和不加完全出现不同结果      
     Properties.Settings setting = new Properties.Settings();
     MessageBox.Show(Properties.Settings.Default.father);
     MessageBox.Show(Properties.Settings.Default.father);
}

Upgrade(),当程序安装多个时,从最新的一个程序所保存在系统的值读取出来并刷新内存里"用户"范围的属性。

至于下面说的*.exe.config*.vshost.exe.config,Settings.settings完全不具备,既无法实现*.exe运行读取,也不会在调试期间*.vshost.exe.config发生变化。

总结

我们可以发现,在项目debug调试下,会在其目录生成app.config,*.exe.config 和 *.vshost.exe.config。它们三者的功能及存在意义都不同(Settings.settings除外)。

app.config 作为开发时配置参数的文件,可以在vs开发时右键属性设置是否复制到可执行程序同目录下(默认始终不复制)。在不复制的情况下,凡进行编译操作在生成可执行程序时会copy该文件为*.exe.config文件和*.vshost.exe.config文件。除非编写程序修改它,一旦生成可执行程序后,没有存在意义。

*.exe.config exe.config文件为程序实际运行时(直接运行.exe程序)直接操作的配置文件,它极大地提高程序的灵活性。例如当程序发布了,我们又想改配置字段。我们不需要去源码中改app.config文件,然后重新编译一遍,这样笨拙繁琐,完全抛去了*.exe.config设计初衷。我们直接修改它,就可以了,执行文件运行只跟它打交道,跟app.config及*.vshost.exe.config都没关系。

*.vshost.exe.config 从名字我们可以看出它跟宿主程序有关系,跟调试有关系,事实上确实如此。该文件主要是在vs调试运行时起作用。在调试运行程序伊始,*vshost.exe.config先copy *.exe.config内容,覆盖*.vshost.exe.config,然后运行程序时操作的配置文件为*.vshost.exe.config,代码对配置文件增删改,都会在这里变动。在调试程序结束时 *.vshost.exe.config再次copy *.exe.config覆盖*.vshost.exe.config,因为exe.config仅为执行文件运行操作,调试不会起任何变动,所以*.vshost.exe.config的内容又变回跟*.exe.config一样。

实际上发布release版本的exe程序时,*.vshost.exe.config 和app.config(如果copy了的话)可以不要的,但是*.exe.config文件必须有,它是要被执行文件读取的,后两者在发布后没有存在的意义。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

WinForm教程(一)App.config等配置文件 的相关文章

  • Winform中提提升重绘效率-背景的设置

    backgrounglayout属性设置为none xff0c 否则会影响重绘效率
  • WinForm 之Control.Invoke 和Control.BeginInvoke 方法的使用 Control 不能在创建它的 Thread 之外被调用。但可以通过 invoke 来保证 C

    WinForm 之Control Invoke 和Control BeginInvoke 方法的使用 Control 不能在创建它的 Thread 之外被调用 但可以通过 invoke 来保证 Control 线程安全 在跨线程更新的时候
  • VS2019使用C++创建winform界面

    用C 43 43 实现winform界面 算是对上一篇文章的补充吧 xff0c 实际上不需要那么繁琐也可以做到 事先准备 打开VS xff0c 新建一个CLR项目 如果在选项中没有发现CLR项目 xff1a 1 找到Visual Studi
  • Winform

    自适应窗口布局 OnLayout 窗口在尺寸变化时 会调用OnLayout方法 所以 在form1 cs文件里重写OnLayout方法即可实现自适应 在OnLayout方法中 我们获取一下窗口的宽度和高度 根据窗口的宽度和高度重新设定控件的
  • .NET编程——利用C#显示图片(WinForm)

    目录 前言 程序设计 前言 在Visual Studio下用C 实现导入图片并显示图片 xff0c 同时可以通过按键来切换图片 程序设计 功能及使用流程 该程序可实现从文件夹中批量导入图片并显示 获取图片左侧显示图片列表 xff0c 右侧显
  • 【matlab】雷达截面积(Radar Cross Section,RCS)(MATLAB部分仿真+Code)

    xfeff xfeff 一 RCS定义 任何具有确定极化的电磁波照射到目标上时 xff0c 都会产生各个方向上的折射或散射 其中散射波分为两部分 xff1a 一 是由与接收天线具有相同极化的散射波组成 xff1b 二 是散射波具有不同的变化
  • Winform datagridview中显示下拉框示例

    方式一 xff1a 如下图所示 xff0c 该方式也是较为简单的一种 你只需要添加一列类型为DataGridViewComboBoxColumn的列 xff0c 然后添加数据源即可 但是我们看到这种方式的下拉列表看起来并不是十分的美观 xf
  • 打造属于自己的正则表达式

    概述 首先需要说明的一点 无论是Winform 还是Webform 都有很成熟的日历控件 无论从易用性还是可扩展性上看 日期的选择和校验还是用日历控件来实现比较好 前几天在CSDN多个版块看到需要日期正则的帖子 所以整理了这篇文章 和大家一
  • 正确解决:坑爹的0xc000007b——应用程序无法正常启动

    问题情景 vs2013 写的一个64位的exe程序 release后带着来自系统目录C Windows SysWOW64 msvcr120 dll 到一个没有runtime的win7环境去运行 没有用到MFC 所以带着这个msvcr120
  • 将控件转换成圆形

    有点儿鸡肋的感觉 System Runtime InteropServices DllImport gdi32 private static extern IntPtr BeginPath IntPtr hdc System Runtime
  • winform开发框架常见的分层模式

    winform开发框架 基础的分层模式 可以分为UI层 User Interface BLL层 Business Logic Layer 业务逻辑层 DAL层 Data Access Layer 数据访问层 业务逻辑层 Business L
  • C#winform——添加不同语言环境下的resx,使得显示文本能随语言环境变化

    添加不同语言环境下的resx 添加不同语言resx文件的两种情形 窗体控件 非窗体控件 为窗体控件添加不同语言resx文件 为非窗体控件添加不同语言resx文件 添加不同语言resx文件的两种情形 窗体控件 1 如下所示 需要在不同语言环境
  • .Net WinForm 中关于输入法打开却无法输入中文总结

    根据前面的兄弟们解决方法我做了下总结 希望对以后遇到此问题的同行提供点帮助 大家如果还有好的方法也请回复提供我 共同学习 出现这个问题时我的输入法设置为 注意我这里使用简体中文美式键盘 然后我删除了简体中文美式键盘 添加了英语 美国 美式键
  • C# 操作JSON的几种方式

    关于Json数据在开发中的重要性 自然不言而喻 本篇通过两种在c 中常用的方式来实现对Json数据的序列化和反序列化 为了实现大多数的需求 我们采用稍微复杂一点的数据模型 首先我们有以下json数据 name 张三 age 20 idCar
  • WindowsFormsHost控件

    WPF和WinForms是两个不同的UI框架 都是由Microsoft创建的 WPF是WinForms的一个更现代的替代品 WinForms是第一个 NET UI框架 为了在两者之间轻松过渡 Microsoft确保WinForms控件仍然可
  • C#桌面应用程序打包

    使用微软的技术开发windows桌面应用程序是很快捷方便的 开发完之后肯定要打包安装才能发布 以前有做过但过长时间没有打包一下子还真有些遗忘 今天专门又重温了一些 干脆写下来算是加深些印象 以后需要时也好有个参考 感觉有很多技术上手都没有太
  • winform记录

    SpeechSynthesizer 下边代码多次调用 会导致内存溢出outofmemory SpeechSynthesizer 需要改为全局静态 private void button Click object sender EventAr
  • 如何将特定类型的数组存储到我的设置文件中?

    由于某种原因 我似乎无法将我的类的数组存储到设置中 这是代码 var newLink new Link Properties Settings Default Links new ArrayList Properties Settings
  • DevExpress WinForms导航控件 - 交付更时尚、体验更好的业务应用(一)

    DevExpress WinForms的Side Navigation 侧边导航 和Nav Panel 导航面板 可以帮助客户交付完全可模仿UI体验的业务解决方案 这些体验在当今流行的应用程序中都可找到 DevExpress WinForm
  • 当我更改配置设置时,Visual Studio 生成“Settings1.Designer.vb”

    有时 并非总是 当我在 我的项目 页面中编辑设置时 当我从那里添加一个设置或编辑一个值时 会收到错误消息 Settings is ambiguous between declaration in Modules

随机推荐

  • 第三方登录之微信扫码登录

    文章目录 1 申请微信接入 2 项目环境搭建 3 后端Controller接口 4 HTML页面代码 5 测试结果 6 补充说明 小伙伴们有各种疑问可以去参考官方文档进行详细的学习下 微信开发文档 此次介绍的将是前后端不分离的微信扫码登录
  • 2022微信小程序填充昵称头像 open-type=“chooseAvatar“

    2021年7月份之后 微信开始加强对微信用户个人信息的安全防控 收回了相关服务端接口 微信后面也推出了前端填写昵称头像的方法 官方代码如下
  • gcc 与 g++ 的区别

    gcc 和 g GCC GNU Compiler Collection GUN 编译器集合 g 是 GCC 中的 GUN C Compiler C 编译器 在已编译好的 C 或者 C 代码的前提下 GCC 编译器已提供了调用接口 可以通过执
  • matlab循环每次循环都把结果输出来,怎么把循环的每一步结果都保存下来啊

    本帖最后由 芒点DK 于 2016 12 9 11 04 编辑 各位前辈请看我的代码 clear workspaces clear clc define variables rmin 0 rmax 8 N 9 dt 1 t 0 tmax 1
  • Flutter: 为字体增加渐变色描边

    文章目录 写在前面 内容 实现描边 实现渐变 一些调整 参考 写在前面 实现如下图的效果 这个数字的内部和外部都有渐变色 内容 实现描边 在网上搜索一轮 可以看到通过用 Stack 来让两个 Text叠加 并对上一个 Text设置外部描边
  • Java接口和多态

    Java接口 Java中的接口是一种定义了一组方法签名的抽象类型 它提供了一种方式来定义类之间的协议 即类应该实现哪些方法 在本教程中 我们将探讨Java中接口的使用和实现 步骤1 定义接口 我们首先需要定义一个接口 接口使用interfa
  • 27 KVM管理系统资源-管理虚拟CPU份额

    文章目录 27 KVM管理系统资源 管理虚拟CPU份额 27 1 概述 27 2 操作步骤 27 KVM管理系统资源 管理虚拟CPU份额 27 1 概述 虚拟化环境下 同一主机上的多个虚拟机竞争使用物理CPU 为了防止某些虚拟机占用过多的物
  • 什么是ARM TCM内存

    什么是ARM处理器上的TCM内存 它是一个驻留在处理器旁边的专用内存 还是一个配置为TCM 的RAM区域 如果它是专用内存 为什么我们可以配置它的位置和大小 TCM Tightly Coupled Memory是一个 或多个 小的专用内存区
  • iOS视频列表开发总结

    最近开发了一个较大的需求 即视频列表 特点是每个视频卡片高度不一致 包含不同的元素 若卡片长度超过一屏 还需要将底部的操作栏悬浮 可以上滑下滑自动切换到下一个播放 整体实现 UITableView作为容器 每一个Item都是一个视频 卡片高
  • webpack打包微信小程序

    webpack打包微信小程序目的 编写小程序代码时也可以引入 npm 上的插件 通过 webpack 打包后可以大大减小小程序代码的体积 项目目录 项目目录 plugin loadpath js src 把小程序的代码放到 src 文件夹内
  • 华为交换机常用的查询命令(自己学习时统计的)

    display 简写dis dis logbuffer 查询交换机日志 dis arp include 10 0 0 1 查询该网段已使用的ip dis arp include 0 0 1 查询该端口下的ip dis clock 查询时间
  • 【Spring】Spring 报错 AbstractMethodError hikari MicrometerMetricsTrackerFactory create

    1 概述 windows下运行一个Spring boot程序报错 如下 org springframework beans factory BeanCreationException Error creating bean with nam
  • vue从node服务器获取文件,用vue上传文件并接收它nodejs

    我想用vuejs上传一个文件到服务器 实际上我不想用表单来处理文件并上传它 我阻止自己提交和处理一些逻辑 所以在开始我想要做一些简单的只是检查它是否是一个PDF格式 如果一切正常 应该指向我的服务器端进行的NodeJS服务器用vue上传文件
  • 熟悉html css,编写HTML和CSS的前端开发中不一定熟悉JavaScript

    原标题 编写HTML和CSS的前端开发中不一定熟悉JavaScript 作为前端开发人员 HTML css Java是必备的知识技能 但是现实工作工作中并非所有的前端都知道Java 根据外国一个网站的匿名调查发现 有17 的开发人员不知道J
  • 2022年中国研究生数学建模竞赛E题-草原放牧策略研究

    一 背景介绍 草原作为世界上分布最广的重要的陆地植被类型之一 分布面积广泛 中国的草原面积为3 55亿公顷 是世界草原总面积的6 8 居世界第二 此外 草原在维护生物多样性 涵养水土 净化空气 固碳 调节水土流失和沙尘暴等方面具有重要的生态
  • react中封装websocket

    websocket js中 import e from express websocket的四个回调函数 onopen onmessage onerror onclose import websocket from Websocket im
  • [现代控制理论]11_现代控制理论串讲_完结_pdf获取

    DR CAN的现代控制理论的笔记就结束了 加上这篇一共11篇 现代控制理论 11 现代控制理论串讲 完结 pdf获取 现代控制理论 10 可观测性与分离原理 观测器与控制器 现代控制理论 9 状态观测器设计 龙伯格观测器 现代控制理论 8
  • Echarts图导出到excel(excel导入图片)

    参照博文echart图导出到pdf 将前台传到后台的二十四位字节编码生成图片 然后将图片导出到excel中 public static void exportEchartsImg HttpServletResponse response L
  • 用云渲染好还是自己搭建传统渲染农场好?

    今天云渲染小编就和大家说说云渲染以及它和传统渲染农场的区别 以及用云渲染好还是自己搭建传统渲染农场好 一 什么是云渲染 云渲染什么意思 首先云渲染是一种依托于云计算的云端服务 用户将本地文件提交到云端服务器 云端计算机集群完成渲染 再将渲染
  • WinForm教程(一)App.config等配置文件

    最近又回到用WinForm开发项目 难免少不了跟数据库打交道 平时也会在App config中写连接字串 但没有仔细深究过 当然除了写数据库字串 肯定还能写别的 我们无论在控制台程序还是窗体程序 都会遇见他 乘代码敲累之际 写篇博客平缓下