Posts Tagged ‘C#/.NET’

解决C#窗体在不同操作系统下显示错乱的问题

星期四, 19 11 月, 2009

将所有Form、UserControl所使用的AutoScaleMode由Font修改为None、DPI或者Inherit,界面即可正常显示

C#生成Excel文件的方法

星期三, 22 4 月, 2009

1. 首先添加Excel的Reference到项目中
右击项目的References,选“Add Reference…”菜单,在COM组里选择“Microsoft Excel 11.0 Object Labrary”(安装的Excel版本不一样这里的版本可能会有变化,我这里是Excel 2003)

2. 新建excel文件实例代码
Microsoft.Office.Interop.Excel.Application app = null;
Microsoft.Office.Interop.Excel.Workbook workbook = null;
Microsoft.Office.Interop.Excel.Worksheet sheet = null;
object missing = System.Reflection.Missing.Value;
try
(更多…)

解决C#中ListView控件动态添加项时闪屏的问题

星期四, 26 3 月, 2009

解决原理:重载ListView控件,让控件支持Double Buffer。

重载的Double Buffer类代码如下:
    /// <summary>
    /// This override list view support double buffer to avoid the twinkling when insert a new item dynamically
    /// </summary>
    public class DoubleBufferListView : ListView
    {
        public DoubleBufferListView()
        {
            SetStyle(ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
            UpdateStyles();
        }
    }
 

摘自:http://www.wewill.cn/n21083c67.aspx

C#项目文件与源程序不在同一级目录时Resources的解决办法

星期五, 26 12 月, 2008

在多人开发的环境,可能为了同步方便把C#的项目文件.csproj移出源程序所在目录,这样在项目中使用Resources时会遇到这些麻烦(附解决办法):

1. 项目属性里Resources和Settings页会提示“This project does contain a default resources/settings file, Click here to create one.”,也就是说项目文件找不到缺省的Resources和Settings文件。

原因:因为IDE只会在项目文件所在目录的Properties子目录查找这两个信息,由于只把项目文件移出,真正的Properties目录仍在源码位置,所以IDE会提示找不到这两组资源。

解决办法:不用去管它,仍使用源码目录下的Properties,后面提到如何使用。

(更多…)

C# Array数组与ArrayList之间的互转

星期三, 24 12 月, 2008

直接看实例吧:
        private void _btnListArray_Click(object sender, EventArgs e)
        {
            string[] a = new string[3];
            a[0] = "fd";
            a[1] = "fe";
            a[2] = "4d";

            ArrayList lst = new ArrayList();
            lst.AddRange(a);

            lst.Add("ffe");
            lst.Add("rrg");
            lst[0] = "aaaa";

            string[] b = (string[])lst.ToArray(typeof(string));
        }
执行结果:a仍然是3个元素并保持不变,lst和b都是5个元素且第一个元素是“aaaa”。

相关链接:
http://www.cnblogs.com/biandande/archive/2008/12/16/1355761.html
http://www.cnblogs.com/smallfa/archive/2008/11/23/1339296.html

C#实现XML系列化和反系列化的总结

星期二, 23 12 月, 2008

常用的系列化定义(using System.Xml.Serialization;)
[XmlAttribute("name")]        // 定义<Tag name="…"></Tag>
[XmlElement("label")]        // 定义<label>…</label>
[XmlIgnoreAttribute()]        // 跳过系列化
[XmlElement("description", IsNullable = false)]        // 定义<description>…</description>,在属性值为null时不显示该元素,即可选
[XmlArray("temp_var_list", IsNullable=false)]        // 定义<temp_var_list><Tag>…</Tag>…<Tag>…</Tag></temp_var_list>,即数组对象的根结点
[XmlArrayItem("temp_var_item")]        // 定义<temp_var_item>…</temp_var_item>…<temp_var_item>…</temp_var_item>,即数据元素的根结点,常与XmlArray组合使用
[XmlRoot("dpd")]        // 定义要结点

几个注意事项
(1)需序列化的字段必须是公共的(public)
(2)需要序列化的类都必须有一个无参的构造函数
(3)枚举变量可序列化为字符串,无需用[XmlInclude]
(4)导出非基本类型对象,都必须用[XmlInclude]事先声明。该规则递归作用到子元素
 如导出ArrayList对象,若其成员是自定义的,需预包含处理:
 using System.Xml.Serialization;
 [XmlInclude(typeof(自定义类))]
(5)Attribute中的IsNullable参数若等于false,表示若元素为null则不显示该元素。
 也就是说:针对值类型(如结构体)该功能是实效的
 若数组包含了100个空间,填充了10个类对象,则序列化后只显示10个节点
 若数组包含了100个空间,填充了10个结构体对象,则序列化后会显示100个节点
(6)真正无法XML序列化的情况
 某些类就是无法XML序列化的(即使使用了[XmlInclude])
  IDictionary(如HashTable)
  System.Drawing.Color
  System.Drawing.Font
  SecurityAttribute声明
 父类对象赋予子类对象值的情况
 对象间循环引用
(7)对于无法XML序列化的对象,可考虑
 使用自定义xml序列化(实现IXmlSerializable接口)
 实现IDictionary的类,可考虑①用其它集合类替代;②用类封装之,并提供Add和this函数
 某些类型需要先经过转换,然后才能序列化为 XML。如XML序列化System.Drawing.Color,可先用ToArgb()将其转换为整数
 过于复杂的对象用xml序列化不便的话,可考虑用二进制序列化

实例
    [SerializableAttribute]        // 定义本类系列化
    [XmlRoot("dpd")]        // 定义为XML的根结点
    public class DataProcessDef

        [XmlElement("is_published")]        // 枚举类型可以系列化成字符串
        public PublishedTypes IsPublished

        [XmlElement("data_item")]        // 输出<data_item>…</data_item>
        public DataItem DataItem

        [XmlArray("property_list")]        // 组合使用,输出<property_list><property_item>…</property_item>…<property_item>…</property_item></property_list>
        [XmlArrayItem("property_item", IsNullable=false)]
        public PropertyItem[] PropertyList

        [XmlElement("custom_item", IsNullable=false)]        // 输出<custom_item>…</custom_item>…<custom_item>…</custom_item>
        public CustomItem[] CustomItems

        [XmlIgnoreAttribute()]        // 不系列化
        public String SourceName

另一种方法
namespace TestCsXml
{
    [Serializable]
    public class SubClass
    {
        public SubClass()
        {

        }

        public SubClass(String str)
        {
            _temp = str;
        }

        [XmlElement("Temp")]
        public String Temp
        {
            get
            {
                return _temp;
            }

            set
            {
                _temp = value;
            }
        }

        private String _temp;
    }

    [Serializable]
    [XmlRoot("Root")]
    [XmlInclude(typeof(SubClass))]
    public class Class1
    {
        public Class1()
        {

        }

        public Class1(String test, String name)
        {
            _test = test;
            _name = name;
        }

        [XmlElement("Test")]
        public String Test
        {
            get
            {
                return _test;
            }

            set
            {
                _test = value;
       &nbsp
;    }
        }

        [XmlAttribute("Name")]
        public String Name
        {
            get
            {
                return _name;
            }

            set
            {
                _name = value;
            }
        }

        [XmlElement("Mooo")]
        public IList Lst
        {
            get
            {
                return _list;
            }

            set
            {
                _list = value;
            }
        }

        [XmlElement("Subclass")]
        public IList Subcls
        {
            get
            {
                return _listObj;
            }

            set
            {
                _listObj = value;
            }
        }

        private String _test;
        private String _name;
        private IList _list = new List<String>();
        private IList _listObj = new List<SubClass>();
    }
}

使用方法
        private void button5_Click(object sender, EventArgs e)
        {
            FileStream fs = new FileStream(@"E:\test2.xml", FileMode.Open);
            XmlSerializer sr = new XmlSerializer(typeof(DataProcessDef));
            DataProcessDef dpd = (DataProcessDef)sr.Deserialize(fs);

            TextWriter wt = new StreamWriter(@"E:\test21.xml");
            sr = new XmlSerializer(typeof(DataProcessDef));

            sr.Serialize(wt, dpd);
            wt.Close();

            MessageBox.Show("OK");
        }
 

C#右击菜单动态设置问题的解决

星期二, 20 11 月, 2007

对于C# TreeView中需要动态在不同结点上显示不同的菜单时,如果在MouseUp事件中判断鼠标选中的结点然后再设置TreeView.ContextMenuStrip时,必须得用Show方法才能显示出菜单,结果会引起鼠标事件不正常。解决办法是在创建TreeNode时直接设置TreeNode.ContextMenuStrip而不是在MouseUp中判断并设置TreeView.ContextMenuStrip,连MouseUp事件都可以省了。

问题解决链接:使用控件ContextMenuStrip的Show方法后鼠标事件不正常,有没有办法解决?

C# PropertyGrid自定义UserControl项不可编辑实现

星期一, 10 9 月, 2007

C#的PropertyGrid控件支持给属性项自定义Converter和Editor,当指定从TypeConverter派生的Converter时可以只能从下拉列表中选择,即属性值不可手工编辑,但不支持UserControl;而指定从UITypeEditor派生的Editor可以支持UserControl但又没办法限制用户直接编辑属性值。

有时我们需要实现既能从UserControl中设定值又不想让用户直接编辑,就象一些Collection一样,只显示"(Collection)"串不可编辑又可以通过下拉或弹出窗体让用户选择。经过多次实现,发现属性项同时指定自定义Converter和Editor可以解决这个问题,后面附一些实现代码。

定义属性项:
        private ItemContent _itemContent = new ItemContent();
        [EditorAttribute(typeof(ContentEditor), typeof(UITypeEditor)),
        TypeConverterAttribute(typeof(ConentConverter)),
        DescriptionAttribute("Select item content")]
        public ItemContent Content
        {
            get { return _itemContent; }
            set { _itemContent = value; }
        }

定义属性内容类:
    public class ItemContent
    {
        private string _type = "Type";
        private string _content = "Content";

        public string Type
        {
            get { return _type; }
        }

        public string Content
        {
            get { return _content; }
            set { _content = value; }
        }
    }

定义Converter:
    public class ConentConverter : ExpandableObjectConverter
    {
        public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
        {
            return true;
        }

        public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
        {
            return true;
        }

        public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
        {
            if (destinationType == typeof(ItemContent))
            {
                return true;
            }

            return base.CanConvertTo(context, destinationType);
        }

        public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
        {
            if (destinationType == typeof(System.String) &&
                value is ItemContent)
            {
                return "(Collection)";
            }

            return base.ConvertTo(context, culture, value, destinationType);
        }
    }

定义Editor:
    public class ContentEditor : UITypeEditor
    {
        public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context)
        {
            return UITypeEditorEditStyle.DropDown;
        }

        public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
        {
            IWindowsFormsEditorService service = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
            SelectControl ctrl = new SelectControl();

            if (value is ItemContent)
            {
                ctrl.Selected = (value as ItemContent).Content;
            }
            service.DropDownControl(ctrl);

            (value as ItemContent).Content = ctrl.Selected;

            return value;
        }
    }

实现SelectControl的UserControl,提供Selected属性,做一些操作。

最后将包含有ItemContent属性的类对象赋给PropertyGrid的SelectedObject即可。

C#PropertyGrid多行编辑实现

星期四, 1 3 月, 2007

如要在PropertyGrid中显示多行编辑时需要重载UITypeEditor类并修改EditorAttribute属性。

1. 重载类MultilineTextEditor
public class MultilineTextEditor : UITypeEditor
{
private static ILog _log = LogManager.GetLogger(typeof(MultilineTextEditor));

public override UITypeEditorEditStyle GetEditStyle(System.ComponentModel.ITypeDescriptorContext context)
{
return UITypeEditorEditStyle.DropDown;
}

public override object EditValue(System.ComponentModel.ITypeDescriptorContext context, IServiceProvider provider, object value)
{
try
{
IWindowsFormsEditorService svc = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));

if (svc != null)
{
if (value is string)
{
TextBox box = new TextBox();

box.AcceptsReturn = true;
box.Multiline = true;
box.Height = 120;
box.BorderStyle = BorderStyle.None;
box.Text = value as string;
svc.DropDownControl(box);

return box.Text;
}
}
}
catch (Exception ex)
{
if (_log.IsErrorEnabled)
{
_log.Error(“MultilineTextEditor error: ” + ex.Message);
}

return value;
}

return value;
}
}

2. 增加EditorAttribute属性
[DescriptionAttribute(“The item description.”),
EditorAttribute(typeof(MultilineTextEditor), typeof(System.Drawing.Design.UITypeEditor))]
public string Description
{
get { return _data.Description; }
set { _data.Description = value; }
}

3. 将包含各个属性的类实例赋给PropertyGrid的SelectedObject属性,即可通过这个实现进行读写操作。

4. PropertyGrid 的部分外观特征
通过 HelpBackColor、HelpForeColor 和 HelpVisible 属性可以更改背景颜色、更改字体颜色或隐藏说明窗格。
通过 ToolbarVisible 属性可以隐藏工具栏,通过 BackColor 属性可以更改工具栏的颜色,通过 LargeButtons 属性可以显示大工具栏按钮。
使用 PropertySort 属性可以按字母顺序对属性进行排序和分类。
通过 BackColor 属性可以更改拆分器的颜色。
通过 LineColor 属性可以更改网格线和边框。

5. 部分属性的显示方式
DescriptionAttribute – 设置显示在属性下方说明帮助窗格中的属性文本。这是一种为活动属性(即具有焦点的属性)提供帮助文本的有效方法。
CategoryAttribute – 设置属性在网格中所属的类别。当您需要将属性按类别名称分组时,此特性非常有用。如果没有为属性指定类别,该属性将被分配给杂项类别。可以将此特性应用于所有属性。
BrowsableAttribute – 表示是否在网格中显示属性。此特性可用于在网格中隐藏属性。默认情况下,公共属性始终显示在网格中。
ReadOnlyAttribute – 表示属性是否为只读。此特性可用于禁止在网格中编辑属性。默认情况下,带有 get 和 set 访问函数的公共属性在网格中是可以编辑的。
DefaultValueAttribute – 表示属性的默认值。如果希望为属性提供默认值,然后确定该属性值是否与默认值相同,则可使用此特性。
DefaultPropertyAttribute – 表示类的默认属性。在网格中选择某个类时,将首先突出显示该类的默认属性。

C#程序启动欢迎窗体实现

星期一, 26 2 月, 2007

当程序在启动过程中需要花一些时间去加载资源时,我们希望程序能显示一个欢迎界面,能简单介绍软件功能的同时还能告知用户该程序还在加载中,使得用户体验更友好。
实现如下:

1. 添加欢迎界面的窗体(比如SlpashForm),做以下调整:
将FormBorderStyle属性设成None,即没有窗体边框
将StartPosition属性设成CenterScreen,即总是居中
将TopMost属性设成True,即总是在顶部
将UseWaitCursor属性设成Ture,即显示等待光标,让人感觉后台还在运行
增加一个PictureBox控件,与欢迎图片大小一致,窗体的大小也设成一致
增加一个ProgressBar控件,将Style设成Marquee,将MarqueeAnimationSpeed设成50

2. 主界面的构造函数改成以下代码:
// Create thread to show splash window
Thread showSplashThread = new Thread(new ThreadStart(ShowSplash));
showSplashThread.Start();

// Time consumed here
InitializeFrame(); // 把原来构造函数中的所有代码移到该函数中

// Abort show splash thread
showSplashThread.Abort();
showSplashThread.Join(); // Wait until the thread aborted
showSplashThread = null;

3. 显示SplashForm的线程函数
///

/// Thread to show the splash.
///

private void ShowSplash()
{
SplashForm sForm = null;
try
{
sForm = new SplashForm();
sForm.ShowDialog();
}
catch (ThreadAbortException e)
{
// Thread was aborted normally
if (_log.IsDebugEnabled)
{
_log.Debug(“Splash window was aborted normally: ” + e.Message);
}
}
finally
{
sForm = null;
}
}

4. 在主窗体的Load事件加激活自己的代码
SetForegroundWindow(Process.GetCurrentProcess().MainWindowHandle);

在使用SetForegroundWindow之前先声明一下
// Uses to active the exist window
[DllImport(“User32.dll”)]
public static extern void SetForegroundWindow(IntPtr hwnd);

实例图: