Visual Studio 2010既简单又绚丽的新功能

开发 后端
在微软Visual Studio 2010的发布会上,我们看到了很多关于VS2010的新特点和功能,文章将介绍几个简单但很绚丽的功能。

Visual Studio 2010正式版刚刚发布不久,但通过微软在发布会上的演示,我们就已经看到了VS2010崭新的用户体验。在这些新功能中,微软也为我们增加了很多应用的扩展。

1、文件的代码行数
2、文件的字符数
3、命名空间的个数
4、字段个数
5、接口个数
6、类的个数
7、函数个数
8、属性个数
9、注释的数量
10、统计文件的大小(Bytes, KB, MB等)。

Visual Studio 2010扩展信息

当您键入您的代码,你会看到信息窗口中的数据会即时更新,这个信息窗口,是利用可扩展面板。你可以把它看成两个部分,每一个部分都可以根据您的需要展开和折叠。这样,当你不需要它时,你将它可以折叠起来,需要的时候,将它展开。下面演示如何展开/折叠这个控件。

VS2010信息窗口

这个控件有三个特殊的状态。***个状态是一个很小的扩展按钮。如上图的***部分。只需点击它,就会打开控件右侧的面板,这个面板显示文件的基本数据,如上图的第二部分。这个控件还有一个可扩展面板,如果点击扩展,就会看到下面的面板,其中显示其他的统计数据,如上图的第三部分。

实现篇:

1、 Microsoft Visual Studio 2010
2、 Visual Studio 2010 SDK

你安装Visual Studio SDK之后,你的Visual Studio 2010中会多出下面这些模板:

Visual Studio 2010模版

这篇文章中,我们使用模板Editor ViewPort Adornment实现这个扩展,此模板将为你的代码编辑器的带来一个装饰品。

其实这个扩展包一个WPF用户控件,我把它放进VS的视窗中就成了信息框。它还含有两个类,一个类用来解析代码,获取代码的相关信息;另一个类用来处理自定义编辑器的事件和当页以及加载的时候将WPF控件添加到页面中。

***步:创建一个Viewport Adornment项目

我们从Extensibility中选择Viewport Adornment模板创建一个项目。这将生成一个SourceManifest文件和两个类文件。一个是Adornment类本身,另外一个是AdornmentFactory类。

第二步:添加一个WPF用户控件

右键单击项目,选择添加一个新的WPF用户控件。为了简单起见,我使用了一个用户控件。这个用户控件实际上包含一个Expander控件,设置它的ExpandDirection = Left,它里面又包含了一些TextBlock控件和另外一个Expander ,设置里面的这个Expander的ExpandDirection = Down。看下面的代码(我删除不必要的元素,使其更简单):

  1. <Expander ExpandDirection="Left" Style="{DynamicResource ExpanderStyle1}"   
  2. x:Name="expMain" > 
  3. <StackPanel> 
  4. <TextBlock x:Name="txtNoLines"   
  5. Text="No of Lines : {0}"   
  6. Margin="25 25 25 0"   
  7. FontSize="12"   
  8. FontFamily="Verdana"   
  9. FontWeight="Bold"   
  10. Foreground="Yellow"></TextBlock> 
  11. <TextBlock x:Name="txtNoCharacters"   
  12. Text="No of Characters : {0}"   
  13. Margin="25 5 25 15"   
  14. FontSize="12"   
  15. FontFamily="Verdana"   
  16. FontWeight="Bold"   
  17. Foreground="Yellow"></TextBlock> 
  18. <Expander x:Name="expCodeInfo" ExpandDirection="Down"   
  19. Header="Code Information"> 
  20. <StackPanel> 
  21. <TextBlock x:Name="txtClassInfo"   
  22. Margin="25 25 25 0"   
  23. FontSize="12"   
  24. FontFamily="Verdana"   
  25. FontWeight="Bold"   
  26. Foreground="LightYellow"/> 
  27. <Line 
  28. Margin="0,4" 
  29. SnapsToDevicePixels="True" 
  30. Stroke="Gold" 
  31. Stretch="Fill" 
  32. X1="0" X2="1"   
  33. /> 
  34. <TextBlock x:Name="txtFileSize" 
  35. Margin="25 5 25 15"   
  36. FontSize="12"   
  37. FontFamily="Verdana"   
  38. FontWeight="Bold"   
  39. Foreground="AliceBlue"/> 
  40. </StackPanel> 
  41. </Expander> 
  42. </StackPanel> 
  43. </Expander> 

你可以看到,代码很简单,两个Expanders,一个用来显示基本的统计信息和另外一个显示扩展的统计信息。我还使用StackPanel来固定TextBlocks布局。现在,如果你看一下后台代码,发现它也一样简单。其实我已经创建了一个CodeInfoTracker类,用它来为我们分析源代码文件。我只是为我们的用户控件添加了一个构造函数,使用户控件更具扩展性而已。

  1. private CodeInfoTracker _cinfo;  
  2. private CodeInfoTracker.Calculators _calculator;  
  3. public ucInfoBox(CodeInfoTracker cinfo)  
  4. : this()  
  5.  {  
  6. this._cinfo = cinfo;  
  7. }  
  8. public void UpdateInfo(CodeInfoTracker info)  
  9. {  
  10. _calculator = info.PerFormCalculate();  
  11. this.txtNoLines.Text = string.Format("No of Lines : {0}",   
  12. _calculator.no_of_lines);  
  13. this.txtNoCharacters.Text = string.Format("No of Characters : {0}",   
  14. _calculator.no_of_characters);  
  15. this.txtFileSize.Text = string.Format("Total File Size : {0}",   
  16. _calculator.totalfilesize);  
  17.  
  18. StringBuilder builder = new StringBuilder();  
  19. if (this._calculator.interfaces != 0)  
  20. builder.AppendFormat("Interfaces : {0}\n\r",   
  21. this._calculator.interfaces);  
  22. if (this._calculator.namespaces != 0)  
  23. builder.AppendFormat("NameSpaces : {0}\n\r",   
  24. this._calculator.namespaces);  
  25. if (this._calculator.classes != 0)  
  26. builder.AppendFormat("Classes : {0}\n\r",   
  27. this._calculator.classes);  
  28. if (this._calculator.methods != 0)  
  29. builder.AppendFormat("Methods : {0}\n\r", this._calculator.methods);  
  30. if (this._calculator.properties != 0)  
  31. builder.AppendFormat("Properties : {0}\n\r",   
  32. this._calculator.properties);  
  33. if (this._calculator.fields != 0)  
  34. builder.AppendFormat("Fields : {0}\n\r", this._calculator.fields);  
  35. if (this._calculator.comments != 0)  
  36. builder.AppendFormat("Comments : {0}\n\r", this._calculator.comments);  
  37. if (builder.Length > 0)  
  38. {  
  39. this.txtClassInfo.Visibility = System.Windows.Visibility.Visible;  
  40. this.txtClassInfo.Text = builder.ToString();  
  41. }  
  42. else  
  43. {  
  44. this.txtClassInfo.Text = "";  
  45. this.txtClassInfo.Visibility = System.Windows.Visibility.Hidden;  
  46. }  

使用了一个结构体Calculators ,这个结构体放置在我们的自定义类中,它有几个int属性用来保存分析源文件获取的所有信息。 info.PerFormCalculate(); 给出分析的结果。这里使用的所有获取的信息来更新了UIElements。 #p#

第三步:创建获取源文件信息的类

虽然代码存在一些复杂性,但是这个类其实很简单。我很感谢CS Parser [^],它帮助我自动地解析源代码。这个类需要一个IWpfTextView对象,它代表着Visual Studio 2010文本编辑器。实际上WpfTextView实现了IWpfTextView。在执行期间这个类接受这个对象。

我可以从WPFTextView.TextSnapshot.GetText()获得到了源代码。在我调用的这个分析的时候,我只需要检测的代码是什么语言写的。开始我想自己来实现,但是感谢上帝,我在WPFTextView中发现已经存在这个对象了。

  1. public enum Language  
  2. {  
  3. CSharp, VisualBasic, Indeterminate  
  4. }  
  5. internal Language DetectLanguage  
  6. {  
  7. get  
  8. {  
  9. string langtype =   
  10. this._view.FormattedLineSource.TextAndAdornmentSequencer.  
  11. SourceBuffer.ContentType.DisplayName;  
  12. if(langtype.Equals("CSHARP",   
  13. StringComparison.InvariantCultureIgnoreCase))  
  14. return Language.CSharp;  
  15. else if(langtype.Equals("BASIC",   
  16. StringComparison.InvariantCultureIgnoreCase))  
  17. return Language.VisualBasic;  
  18. else  
  19. return Language.Indeterminate;  
  20. }  

DetectLanguage妥善地利用WPFTextView对象的FormattedLineSource.TextAndAdornmentSequencer。SourceBuffer.ContentType.DisplayName,这个属性告诉我是使用了哪种语言。之后我创建了一个新的方法PerFormCalculate,用它来解析源代码,它返回一个Calculation结构对象。

第四步:创建 Adornment Factory 类

回到这个扩展,我创建一个Adornment(InfoBoxAdornmentFactory)的Factory类。这个类继承IWpfTextViewCreationListener,用来监听WPF的编辑和创建事件。

  1. [Export(typeof(IWpfTextViewCreationListener))]  
  2. [ContentType("text")]  
  3. [TextViewRole(PredefinedTextViewRoles.Document)]   
  4. internal sealed class InfoBoxAdornmentFactory : IWpfTextViewCreationListener  
  5. {  
  6. [Export(typeof(AdornmentLayerDefinition))]  
  7. [Name("AlwaysVisibleInfoBox")]  
  8. [Order(After = PredefinedAdornmentLayers.Selection)]  
  9. [TextViewRole(PredefinedTextViewRoles.Interactive)]  
  10. public AdornmentLayerDefinition editorAdornmentLayer = null;  
  11. public void TextViewCreated(IWpfTextView textView)  
  12. {  
  13. new AlwaysVisibleInfoBox(textView);  
  14. }  
  15. }  

这里,你可以看到我在这个类上使用了很多Attributes,像ContentType,它定义了我们只处理文本格式的编辑器;还有TextViewRole,它定义了将被这个类处理的textview的类型。在这个类中,我创建了一个AdornmentLayerDefination对象。可能你想知道我们没有使用它,无什么还需要定义它呢,它只是用来配置属性的。Order属性指定,当,InfoBox在层被选之后监听,Name是编辑扩展的名字。

第五步:创建Adornment 类

Adornment类实际创建了一个WPF用户控件对象,并设置它的视图画布。在内部构造函数中,我处理IWpfTextView.LayoutChanged事件,当代码修改或者布局改变的时候,就触发这个事件。

因此,通过这一事件,当我们编辑的文档时,我们可以很容易地得到回调。当浏览器编辑器的大小改变时,我还通过处理WPFTextView.ViewportHeightChanged,WPFTextView.ViewportWidthChanged得到回调,使我们可以重新定位相应的UserControl。

  1. public AlwaysVisibleInfoBox(IWpfTextView view)  
  2. {  
  3. _view.LayoutChanged += this.OnLayoutChanged;  
  4. this.GetLayer();  
  5.  }  
  6. private void GetLayer()  
  7. {  
  8.  _adornmentLayer = this._view.GetAdornmentLayer("AlwaysVisibleInfoBox");  
  9. _view.ViewportHeightChanged += delegate { this.onSizeChange(); };  
  10. _view.ViewportWidthChanged += delegate { this.onSizeChange(); };  
  11. }  
  12. private void OnLayoutChanged(object sender, TextViewLayoutChangedEventArgs e)  
  13. {  
  14. this._info = new CodeInfoTracker(_view);  
  15. this.infobox.UpdateInfo(this._info);  
  16. }  
  17. public void onSizeChange()  
  18. {  
  19.  
  20. _adornmentLayer.RemoveAllAdornments();  
  21. Canvas.SetLeft(infobox, _view.ViewportRight - 255);  
  22.  Canvas.SetTop(infobox, _view.ViewportTop + 10);  
  23.  
  24. _adornmentLayer.AddAdornment(AdornmentPositioningBehavior.ViewportRelative,   
  25.  null, null,   
  26. infobox, null);  
  27.  } 

因此,构造函数只是调用GetLayer来获取的Layer对象,发生在ViewportHeightChanged和ViewportWidthChanged ViewPortSizeChage事件。当一个布局改变时,我就能更新这个用户的控件。至此,我们成功地建立我们的扩展。你可以使用F5运行它,它会打开一个Visual Studio 2010的Experimental实例。

安装和卸载这个扩展:

安装和卸载这个扩展是非常容易的。当您编译项目后,它会产生一个VSIX文件。您可以只需双击这个文件,它会自动安装到Visual Studio 2010。

安装和卸载这个扩展

文章转自海纳百川的博客,

原文地址:http://www.cnblogs.com/zhuqil/archive/2010/04/15/Visual-Studio-Extension.html

 

【编辑推荐】

  1. 图解Visual Studio 2010中的UML建模功能
  2. 解密中国研发团队如何开发VS2010新特性
  3. Visual Studio 2010化繁为简 令项目管理更轻松
  4. Visual Studio 2010 Lab Management功能
  5. Visual Studio 2010将再度拥抱UML

 

责任编辑:王晓东 来源: 博客园
相关推荐

2010-01-13 09:11:04

Visual Stud

2013-11-13 10:07:26

Visual Stud微软

2010-02-22 14:00:29

Visual Stud

2010-04-08 15:14:59

Visual StudASP.NET 4.

2013-06-04 17:08:19

Visual Stud

2009-10-22 14:50:00

Visual Stud

2009-05-19 09:21:50

Visual Stud云计算并行编程

2010-01-15 09:30:22

Visual Stud

2009-12-02 11:22:14

Visual Stud

2009-04-23 14:05:28

Visual Stud历史调试功能

2010-04-12 08:43:45

Visual Stud

2012-04-25 11:04:13

Visual Stud

2009-12-02 09:43:38

Visual Stud

2009-10-22 09:47:33

Visual Stud

2009-12-02 10:44:30

Visual Stud

2010-04-15 08:40:00

UML建模Visual Stud

2009-03-10 10:21:05

灾难恢复Restart Manvs

2009-10-19 09:48:24

Visual Stud

2009-08-21 13:29:20

Visual Stud

2009-11-19 10:55:33

Visual Stud
点赞
收藏

51CTO技术栈公众号