发现这个有点像 Bug 又不太像 Bug 的东西的过程是这样的:

我继承自 ContentControl 写了一个 MyContentControl ,在其中定义了一个叫做 IconProperty
的依赖属性及其对应的 CLR 属性并且在其静态构造中调用了 DefaultStyleKeyProperty.OverrideMetadata
方法,代码很少,看起来是这个样子的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class MyContentControl: ContentControl {

static MyContentControl() {
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyContentControl), new FrameworkPropertyMetadata(typeof(MyContentControl)));
}

public ImageSource Icon {
get {
return (ImageSource) GetValue(IconProperty);
}
set {
SetValue(IconProperty, value);
}
}

public static readonly DependencyProperty IconProperty = DependencyProperty.Register("Icon", typeof(ImageSource), typeof(MyContentControl));
}

其中的 Icon 属性声明类型为 ImageSource ,目的简单明了,当然就是给这个控件加个图标了。

然后再给这个自定义控件定义一个放在 Generic.xaml 里的 Template ,一样很简单,只是用一个 StackPanel 把它的
Icon 和 Content 包起来,代码是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<Style TargetType="{x:Type local:MyContentControl}">
<Style.Setters>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MyContentControl}">
<StackPanel>
<Image Source="{TemplateBinding Icon}" Stretch="Fill"/>
<ContentPresenter Content="{TemplateBinding Content}"/>
</StackPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
阅读全文 »

WPF中的ItemsControl定义了 ItemContainerStyle 这一属性,顾名思义,该属性用来给
ItemsControl中包含的每一个Item的容器定义样式 。

比如在ListBox中这个容器就是ListBoxItem,在TabControl中这个容器就是TabItem。

下面是 ItemContainerStyle 的一种简单应用:

XAML:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<Window>
<StackPanel>
<ListBox Name="itemsControl" ItemsSource="{Binding}">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=OneTime}"/>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Text}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</Window>

在这段 XAML中 定义了一个ListBox,在其ItemTemplate中有一个TextBlock绑定到数据实体的Text属性上。在其
ItemContainerStyle 中将其每个
Item的IsSelected属性绑定到数据实体的IsSelected上。其数据实体的生成在下面的代码中:

阅读全文 »

最近需要在 .NET 4 的环境中调用 GDAL 库。 GDAL 本身是一套非托管类库,不过还好提供了托管的 Wrapper 。

这些托管的程序集被包含在了 FWTools 的安装包中, FWTools 中带的版本依赖于 gdal_fw.dll, gdal_fw.dll
是 GDAL 核心类库的修改版,而它依赖的其他非托管程序集太多了,加起来有 18M 左右。所以还是自己下载代码编译的好。

这篇文章
介绍了 1.4 版本的编译方法,该方法同样适用于现在的 1.7 版本。

编译好之后引用、调用、 Debug 都没问题,一切正常,但是如果用 Release 编译并在 VS 之外运行的话则会报出
AccessViolationException ,异常信息提示说访问了受保护的内存。我的第一反应就是托管的 Wrapper 中用 P/Invoke
调用了非托管程序集,而非托管程序集导致了这个问题。但是这个猜测并不能解释为什么只有在 .NET 4+Release+IDE
外运行的情况下才会出错的现象。

猜来猜去,找来找去找到了问题的所在:

GDAL 的托管 Wrapper 中有一个叫做 SWIGStringHelper
的类型,该类型的静态构造方法中执行了一些比较重要的初始化操作。另外一个叫做 OsrPINVOKE 的类中声明了一个 SWIGStringHelper
类型的私有静态字段,并在声明时就初始化了该字段,而且 OsrPINVOKE 中没有显式声明的静态构造。

阅读全文 »

MEF编程指南(前两节)

在应用程序中使用MEF

在应用程序中使用MEF需要创建一个CompositionContainer的实例,向其中添加可组合的部件,将宿主应用包含进去然后组合。

以下是使用MEF需要用到的步骤:

1、 创建一个宿主类。在接下来的示例中,我们将会使用一个控制台应用,所以宿主也就是Program类了。

2、 引用System.ComponentModel.Composition程序集

阅读全文 »

.NET 4.0 FAQ 第一部分—DLR

简介

本篇文章中我们将讨论.NET FrameWork 4.0提供了哪些新特性。然后再探讨DLR特性 中的动态对象和Expando对象。我们也将会创建一个Exp
ando对象来看我们可以从中获得哪些益处。很多的开发人员误以为动态对象是用来替代反射和object类型的,我们也将会纠正这种错误的概念。

.NET 4.0中有哪些重要的新特性?

与其去浏览.NET 4.0冗长的新特性列表,我们还是专注于我们认为最重要的三项新特性上吧。

• WF和WCF 4.0:这是.NET

阅读全文 »

昨天遇到了一个 Bug ,如果在浏览器中打开多个标签,并把其中一个标签拖拽到主窗口的一侧来划分出独立的一个区域,然后在新区域中通过点击加号键添加的新标签内不会被添加上 WebBrowser 。

说得好绕嘴啊,截张图吧:

而且没有加上 WebBrowser 的标签的标题是 new content (我们在 AvalonDock 中给新标签的默认标题)而不是 New Tab (客户代码中重新赋的值)。

OK ,问题明了了,是不是新添加的标签的 Got_Focus 没能够挂到客户代码中的方法上去呢?

的确是这样,当我们把一个标签( DocumentContent )拖拽到一侧从而划分出一个新区域的时候, AvalonDock 会创建一个新的 DocumentPane 来代表这个新区域。

阅读全文 »

闲话少叙,书接上文。

现在我们已经通过 ReStyle 给 DocumentPane 加上了一个加号的按钮,并且可以通过点击该按钮给 DocumentPane 的
Items 添加一个 DocumentContent 了。

不过每个新添加进来的 DocumentContent 内部都是空的,而我们需要的是每个新标签中都有一个 WebBrowser
,要实现这一点很简单,只要给 DocumentContent 的 Content ( DocumentContent 是
ContentControl 的子类)属性赋值为一个 WebBrowser 的实例就 OK 了。

但是这不应该是 AvalonDock 的默认行为,所以我们要把这部分写到客户端 – 也就是引用 AvalonDock.dll
文件或者直接引用 AvalonDock 工程的 Solution 中去。

如何可以在客户端得知有一个新的 DocumentContent 被添加进 DocumentPane 中去了呢?自然是用事件了。

首先来写一个自定义的 EventArgs 吧:

阅读全文 »

AvalonDock 是 CodePlex 上的一个开源项目,利用它可以很容易的做出类似于 VS 的 UI 效果。

下图是 AvalonDock 源码中自带的一个 Demo :

我们可以用这款第三方控件为基础来制作多标签浏览器。

下面是最终效果图:

甚至可以把其中一个标签拖出主窗体成为一个独立的窗口:

阅读全文 »

Words Via Subtitle 改进:视频播放例句、加快生成 WPS 文档的速度

关于 Words Via Subtitle 的介绍:

1
http://blog.csdn.net/cuipengfei1/archive/2009/09/03/4516588.aspx

2
http://blog.csdn.net/cuipengfei1/archive/2009/09/10/4539180.aspx

最近给这个小程序添加了视频播放例句的功能,使用方法如下:

载入字幕文件并指定了与之对应的视频文件之后,选中某个感觉生疏的单词,然后点击播放例句按钮,该单词所在句子就会以视频的方式开始播放,播完该句子视频暂停。其实这
个功能写起来也挺简单的,就是在字幕中找到一个单词所在句子对应的时间信息,然后依照该时间段播放视频。

阅读全文 »

上周写了一个
通过英文剧集、电影学单词的小工具
,这几天又做了一点小的改进。主要是下面这两点:

  1. 显示单词解释的同时显示其在剧中出现的语境,关键单词红色显示。效果如下:

  1. 导出文档。可以把列表中的单词,其简明解释和在剧中出现的语境保存到文档中。关键词开头绿色显示,例句中红色显示。效果如下:

为什么要写这个功能呢?因为九月中下旬有很多美剧要回归,包括 TBBT , Lie to me , Heroes , Fringe 。到时候每
一集出来之后可以用这个程序迅速的把一集中出现的生词,其音标及解释还有语境总结出来。可以把它发到博客里,或者发到美剧对应的社区或者贴吧里去,会比一般的影迷手工
总结的快很多。

阅读全文 »

我平时很喜欢看美剧和电影。而如果看中文字幕(看英文字幕也是一样)的话,注意力就会集中于阅读文字、理解剧情,练习听力的目的就落空了。而如果不看字幕的话,对话中
的很多生词就会随着对句子的大致理解而溜过去了,所以最好的办法就是看之前把对白中会出现的单词预览一次以为预习,看的过程中再熟悉一次,看完之后还可以针对用得到的
单词再记一次。为了实现这个目的,我写了一个小程序。

使用方式如下:

运行 WordsViaSubtitle.exe

可以通过程序中的搜索框搜索字幕文件(是射手网提供的,赞美射手 O(∩_∩)O哈!!)

阅读全文 »

前几天发的程序只可以用于easyMule1.X版本,今天改写了一下,可以适用于2.0

使用方法:

运行 EasyMulePowerOff.exe

会提示您设置电驴的安装路径,设置好之后会检查到有没有未完成的任务:

显示我有一个未完的任务,看一下电驴中

阅读全文 »

由于电驴官方鼓励尽量多的上传,所以不提供下载完关机的功能。于是我自己写了个小工具来实现这个功能。

使用方法:

运行 EasyMulePowerOff.exe

会提示您设置电驴的安装路径,设置好之后会检查到有没有未完成的任务:

阅读全文 »

近日闻悉国内某出版社即将出版《 Head First C# 》的中文版,为避免版权纠纷,本“山寨”系列将停止翻译和更新。

从去年 10 月开始利用课余时间翻译这本书,到现在翻译完了将近 13 章,总计 12 万余字。

剩余的正文内容已不足百页,无法做到有始有终,颇为遗憾。

感谢 CSDN 和 VeryCD 各位朋友一直以来的关注、支持、鼓励和批评。

2009 年 8 月 7 日

阅读全文 »

欲验证的结论: 接口引用指向装箱后的值类型时无需拆箱 。

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
interface SomeInterface

{
void MethodInInterface();
}

struct OneValueType : SomeInterface

{
public void MethodInInterface()

{
Console.WriteLine("get called");
}
}

class TestUnBox

{
public static void Main()

{
}

private static void CastStruct()

{
OneValueType ovt = new OneValueType();

object o = ovt; //Box

((OneValueType) o).MethodInInterface();
}

private static void CastInterface()

{
OneValueType ovt = new OneValueType();

object o = ovt; //Box

((SomeInterface) o).MethodInInterface();
}
}

其中 OneValueType 是值类型,它实现了 SomeInterface 。

两个方法 CastStruct 和 CastInterface 分别把装箱之后的值类型转型为 OneValueType 和
SomeInterface 。预计的结果是第二个方法无需拆箱,查看 IL 来验证:

这是 CastStruct ():

阅读全文 »

原地址在我的CSDN
Blog:http://blog.csdn.net/cuipengfei1/archive/2009/07/19/4362245.aspx

① Object 的静态方法 ReferenceEquals :

只适用于判断两个引用是否指向同一个实例,不适用于值类型(或者说用于值类型是没意义的,因为永远返回 false )。如下:

1
2
3
4
5
TestEqual  te =  new  TestEqual  ();

bool b1= object .ReferenceEquals(te,te);

bool b2 = object .ReferenceEquals(1, 1);

b1 为 true , b2 为 false 。 b2 为 false 的原因是两个整型值 1 装箱之后是两个不同的
Object 实例。

② Object 中定义的实例级虚方法 Equals :

阅读全文 »

as 看起来很好用的样子,不会抛出异常,只要根据返回值是否为 null来做不同的处理就可以了。但是它也不是万金油,以下的情况 as 就不适用:

①值类型

比如:

1
2
3
double  d = 100.0;

int valueType = d as int ;

这两句代码就直接通不过编译,给出的原因是: as 运算符必须用于引用类型或可以为 null类型 (“int” 是一种不可以为 null
值的类型 )

想一下也合理, as 在失败时会返回 null,而值类型是不可以为 null的( INullable 除外)。

阅读全文 »

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Collections;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string str = "aaeaabbebbccececddeddd";

List<char> charList = new List<char>(str.ToCharArray());
int len = charList.Count;

Dictionary<char, int> charD = new Dictionary<char, int>();

int lastTime = 0;

while (charList.Count != 0)
{
int count = CountAChar(charList);

if (count > lastTime)
{
charD.Clear();
charD.Add(charList[0], count);
lastTime = count;
}

else if (count == lastTime)
{
charD.Add(charList[0], count);
lastTime = count;
}

DeleteAChar(count, charList);
}

foreach (KeyValuePair<char, int> kv in charD)
{
Console.WriteLine("{1}有{0}个", kv.Value.ToString(), kv.Key.ToString());
}

Console.WriteLine("----------------------------------------");
SecondProgram.SecondWay(str);
Console.WriteLine("----------------------------------------");
ThirdClass.ThirdWay(str);
Console.Read();
}

static void DeleteAChar(int num, List<char> cl)
{
char c = cl[0];

for (int i = 0; i < num; i++)
{
cl.Remove(c);
}
}

static int CountAChar(List<char> cl)
{
int ret = 0;

foreach (char c in cl)
{
if (c == cl[0])
{
ret++;
}
}

return ret;
}
}

//-----------------------------------------------------------------
class SecondProgram
{
public static void SecondWay(string str)
{
int len = str.Length;
char[] strArray = str.ToCharArray();
int[] count = new int[len];
for (int y = 0; y < len; y++) //将count数组的每个单元初始为0
count[y] = 0;

for (int y = 0; y < len; y++) //将当前字符与之后的字符进行比较,相同count数组中对应索引处++
{
for (int yy = y; yy < len; yy++)
{
if (strArray[y].Equals(strArray[yy]))
{
count[y]++;
}
}
}

ArrayList maxCountArr = new ArrayList();
int maxCount = count[0];

for (int y = 0; y < len; y++) //获得出现次数的最大值
{
if (count[y] > maxCount)
{
maxCount = count[y];
}
}

for (int y = 0; y < len; y++)
//最大值与count数组中的每个数进行比较,相同则出现次数相同,把索引加入到maxCountArr
{
if (count[y] == maxCount)
{
maxCountArr.Add(y);
}
}

for (int y = 0; y < maxCountArr.Count; y++) //输出
{
Console.Write("Str" + (y + 1) + ":" + strArray[(int) maxCountArr[y]] + "/n");
}
}
}

/// <summary>
/// 第三种方式
/// </summary>
class ThirdClass
{
/// <summary>
/// 还是LinQ最简便
/// </summary>
/// <param name="str"></param>
public static void ThirdWay(string str)
{
var resultGroup = from aChar in str.ToCharArray()
group aChar by aChar;

int max = 0;

foreach (var one in resultGroup)
{
if (one.Count() > 0)
{
max = one.Count();
}
}

foreach (var one in resultGroup)
{
if (one.Count() == max)
{
Console.WriteLine("{0}字符出现了{1}次", one.Key, max);
}
}
}
}
}

今天成都血液中心来采血。我去献了300CC的血,今天才知道自己是O型血~~

手里拿着送我的一把天堂伞和《无偿献血证》回寝室。门口大爷(大概60岁)正在择菜,看到我,说:“你们去献血了?好同学!为社会主义献血!”

O(∩_∩)O 年代的烙印啊

刚才在食堂吃完午饭回寝室的路上听广播,大意是:学校组织全校党员、领导、干部,本着实践科学发展观的精神进行了深入的调查研究,仅专题座谈会就召开了192场。终于
得出一个重要结论:就业率对于我们学校是很重要的。

TMD……彻底被雷了一把…

今天公布了CET-SET(口语)的成绩,在去上课的路上用手机查询。得了一个A。

到教室,没过几分钟收到一封邮包。是O‘reilly寄来的笔记本(是真的笔记本,不是laptop……)

封面是这样的

O(∩_∩)O哈哈~

阅读全文 »

刘义军老师留的作业

代码简单,一看就懂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace GDI_DDA
{
public partial class Form1 : Form
{
int pointSize = 22;
int width = Screen.PrimaryScreen.WorkingArea.Width;
int height = Screen.PrimaryScreen.WorkingArea.Height;

public Form1()
{
InitializeComponent();
}

void DrawGrid(Graphics gra)
{
for (int i = 0; i <= Width; i += pointSize)
{
gra.DrawLine(Pens.Black, i, 0, i, height);
}

for (int i = 0; i <= height; i += pointSize)
{
gra.DrawLine(Pens.Black, 0, i, Width, i);
}
}

void MyDrawLine(Graphics gra, float startX, float startY, float endX, float endY)
{
float dx = endX - startX;
float dy = endY - startY;
float delta = dy / dx;
float
y = startY;
for (int x = (int) startX; x <= endX; x++, y += delta)
{
DrawEllipseByCenter(gra, Pens.Red, x * pointSize, y * pointSize, pointSize * 0.5f);
}
}

void DrawEllipseByCenter(Graphics g, Pen p, float centerX, float centerY, float r)
{
g.FillEllipse(Brushes.Red, centerX - r * 0.5f, centerY - 0.5f, 2 * r, 2 * r);
}

private void Form1_Paint(object sender, PaintEventArgs e)
{
Graphics myGra = e.Graphics;
DrawGrid(myGra);
MyDrawLine(myGra, 3, 5, 47, 25);
myGra.DrawLine(Pens.Red, 3 * pointSize, 5 * pointSize, 47 * pointSize, 25 * pointSize);
myGra.Dispose();
}
}
}

昨天读了《Effective C#》的第一个条款“使用属性代替可访问的数据成员”,讲到要把公有字段修改为私有字段,并用公有属性把它封装起来。这一点不难理解,
不过里面提到了一个关于二进制兼容性的问题,很是有趣,今天来验证一下。

验证思路:创建一个类库内有一个public的类,该类内有一个public的字段。另外创建一个WinForm程序去读区该字段并显示。然后修改类库中的字段为属性
。再去运行WinForm,就应该会出错了。出错具体原因请参看《Effective C#》讲解。

开始吧!

创建一个ClassLibrary,叫做TheDLL。代码如下:

1
2
3
4
public class DataHolder
{
public String Data = "Hey! Hey!You!You!";
}

用它生成一个dll。

阅读全文 »

所谓女生版就是指的GUI稍微美化了一点点,我承认是标题党….

注意:需要有.net Framework 2.0才可以运行

.net Framework 2.0下载地址(如果你的电脑没有请在这儿下载):
http://www.gougou.com/search?search=.net%20Framework%202.0&id=0

学分绩点计算器下载地址:
http://download.csdn.net/source/993661
(要有CSDN账号才可以下载)

没有CSDN账号请向 397649079@QQ.com 索取

阅读全文 »