Visual Studio 2010既簡(jiǎn)單又絢麗的新功能
Visual Studio 2010正式版剛剛發(fā)布不久,但通過微軟在發(fā)布會(huì)上的演示,我們就已經(jīng)看到了VS2010嶄新的用戶體驗(yàn)。在這些新功能中,微軟也為我們?cè)黾恿撕芏鄳?yīng)用的擴(kuò)展。
1、文件的代碼行數(shù)
2、文件的字符數(shù)
3、命名空間的個(gè)數(shù)
4、字段個(gè)數(shù)
5、接口個(gè)數(shù)
6、類的個(gè)數(shù)
7、函數(shù)個(gè)數(shù)
8、屬性個(gè)數(shù)
9、注釋的數(shù)量
10、統(tǒng)計(jì)文件的大?。˙ytes, KB, MB等)。
當(dāng)您鍵入您的代碼,你會(huì)看到信息窗口中的數(shù)據(jù)會(huì)即時(shí)更新,這個(gè)信息窗口,是利用可擴(kuò)展面板。你可以把它看成兩個(gè)部分,每一個(gè)部分都可以根據(jù)您的需要展開和折疊。這樣,當(dāng)你不需要它時(shí),你將它可以折疊起來,需要的時(shí)候,將它展開。下面演示如何展開/折疊這個(gè)控件。
這個(gè)控件有三個(gè)特殊的狀態(tài)。***個(gè)狀態(tài)是一個(gè)很小的擴(kuò)展按鈕。如上圖的***部分。只需點(diǎn)擊它,就會(huì)打開控件右側(cè)的面板,這個(gè)面板顯示文件的基本數(shù)據(jù),如上圖的第二部分。這個(gè)控件還有一個(gè)可擴(kuò)展面板,如果點(diǎn)擊擴(kuò)展,就會(huì)看到下面的面板,其中顯示其他的統(tǒng)計(jì)數(shù)據(jù),如上圖的第三部分。
實(shí)現(xiàn)篇:
1、 Microsoft Visual Studio 2010
2、 Visual Studio 2010 SDK
你安裝Visual Studio SDK之后,你的Visual Studio 2010中會(huì)多出下面這些模板:
這篇文章中,我們使用模板Editor ViewPort Adornment實(shí)現(xiàn)這個(gè)擴(kuò)展,此模板將為你的代碼編輯器的帶來一個(gè)裝飾品。
其實(shí)這個(gè)擴(kuò)展包一個(gè)WPF用戶控件,我把它放進(jìn)VS的視窗中就成了信息框。它還含有兩個(gè)類,一個(gè)類用來解析代碼,獲取代碼的相關(guān)信息;另一個(gè)類用來處理自定義編輯器的事件和當(dāng)頁以及加載的時(shí)候?qū)PF控件添加到頁面中。
***步:創(chuàng)建一個(gè)Viewport Adornment項(xiàng)目
我們從Extensibility中選擇Viewport Adornment模板創(chuàng)建一個(gè)項(xiàng)目。這將生成一個(gè)SourceManifest文件和兩個(gè)類文件。一個(gè)是Adornment類本身,另外一個(gè)是AdornmentFactory類。
第二步:添加一個(gè)WPF用戶控件
右鍵單擊項(xiàng)目,選擇添加一個(gè)新的WPF用戶控件。為了簡(jiǎn)單起見,我使用了一個(gè)用戶控件。這個(gè)用戶控件實(shí)際上包含一個(gè)Expander控件,設(shè)置它的ExpandDirection = Left,它里面又包含了一些TextBlock控件和另外一個(gè)Expander ,設(shè)置里面的這個(gè)Expander的ExpandDirection = Down??聪旅娴拇a(我刪除不必要的元素,使其更簡(jiǎn)單):
- <Expander ExpandDirection="Left" Style="{DynamicResource ExpanderStyle1}"
- x:Name="expMain" >
- <StackPanel>
- <TextBlock x:Name="txtNoLines"
- Text="No of Lines : {0}"
- Margin="25 25 25 0"
- FontSize="12"
- FontFamily="Verdana"
- FontWeight="Bold"
- Foreground="Yellow"></TextBlock>
- <TextBlock x:Name="txtNoCharacters"
- Text="No of Characters : {0}"
- Margin="25 5 25 15"
- FontSize="12"
- FontFamily="Verdana"
- FontWeight="Bold"
- Foreground="Yellow"></TextBlock>
- <Expander x:Name="expCodeInfo" ExpandDirection="Down"
- Header="Code Information">
- <StackPanel>
- <TextBlock x:Name="txtClassInfo"
- Margin="25 25 25 0"
- FontSize="12"
- FontFamily="Verdana"
- FontWeight="Bold"
- Foreground="LightYellow"/>
- <Line
- Margin="0,4"
- SnapsToDevicePixels="True"
- Stroke="Gold"
- Stretch="Fill"
- X1="0" X2="1"
- />
- <TextBlock x:Name="txtFileSize"
- Margin="25 5 25 15"
- FontSize="12"
- FontFamily="Verdana"
- FontWeight="Bold"
- Foreground="AliceBlue"/>
- </StackPanel>
- </Expander>
- </StackPanel>
- </Expander>
你可以看到,代碼很簡(jiǎn)單,兩個(gè)Expanders,一個(gè)用來顯示基本的統(tǒng)計(jì)信息和另外一個(gè)顯示擴(kuò)展的統(tǒng)計(jì)信息。我還使用StackPanel來固定TextBlocks布局。現(xiàn)在,如果你看一下后臺(tái)代碼,發(fā)現(xiàn)它也一樣簡(jiǎn)單。其實(shí)我已經(jīng)創(chuàng)建了一個(gè)CodeInfoTracker類,用它來為我們分析源代碼文件。我只是為我們的用戶控件添加了一個(gè)構(gòu)造函數(shù),使用戶控件更具擴(kuò)展性而已。
- private CodeInfoTracker _cinfo;
- private CodeInfoTracker.Calculators _calculator;
- public ucInfoBox(CodeInfoTracker cinfo)
- : this()
- {
- this._cinfo = cinfo;
- }
- public void UpdateInfo(CodeInfoTracker info)
- {
- _calculator = info.PerFormCalculate();
- this.txtNoLines.Text = string.Format("No of Lines : {0}",
- _calculator.no_of_lines);
- this.txtNoCharacters.Text = string.Format("No of Characters : {0}",
- _calculator.no_of_characters);
- this.txtFileSize.Text = string.Format("Total File Size : {0}",
- _calculator.totalfilesize);
- StringBuilder builder = new StringBuilder();
- if (this._calculator.interfaces != 0)
- builder.AppendFormat("Interfaces : {0}\n\r",
- this._calculator.interfaces);
- if (this._calculator.namespaces != 0)
- builder.AppendFormat("NameSpaces : {0}\n\r",
- this._calculator.namespaces);
- if (this._calculator.classes != 0)
- builder.AppendFormat("Classes : {0}\n\r",
- this._calculator.classes);
- if (this._calculator.methods != 0)
- builder.AppendFormat("Methods : {0}\n\r", this._calculator.methods);
- if (this._calculator.properties != 0)
- builder.AppendFormat("Properties : {0}\n\r",
- this._calculator.properties);
- if (this._calculator.fields != 0)
- builder.AppendFormat("Fields : {0}\n\r", this._calculator.fields);
- if (this._calculator.comments != 0)
- builder.AppendFormat("Comments : {0}\n\r", this._calculator.comments);
- if (builder.Length > 0)
- {
- this.txtClassInfo.Visibility = System.Windows.Visibility.Visible;
- this.txtClassInfo.Text = builder.ToString();
- }
- else
- {
- this.txtClassInfo.Text = "";
- this.txtClassInfo.Visibility = System.Windows.Visibility.Hidden;
- }
- }
使用了一個(gè)結(jié)構(gòu)體Calculators ,這個(gè)結(jié)構(gòu)體放置在我們的自定義類中,它有幾個(gè)int屬性用來保存分析源文件獲取的所有信息。 info.PerFormCalculate(); 給出分析的結(jié)果。這里使用的所有獲取的信息來更新了UIElements。 #p#
第三步:創(chuàng)建獲取源文件信息的類
雖然代碼存在一些復(fù)雜性,但是這個(gè)類其實(shí)很簡(jiǎn)單。我很感謝CS Parser [^],它幫助我自動(dòng)地解析源代碼。這個(gè)類需要一個(gè)IWpfTextView對(duì)象,它代表著Visual Studio 2010文本編輯器。實(shí)際上WpfTextView實(shí)現(xiàn)了IWpfTextView。在執(zhí)行期間這個(gè)類接受這個(gè)對(duì)象。
我可以從WPFTextView.TextSnapshot.GetText()獲得到了源代碼。在我調(diào)用的這個(gè)分析的時(shí)候,我只需要檢測(cè)的代碼是什么語言寫的。開始我想自己來實(shí)現(xiàn),但是感謝上帝,我在WPFTextView中發(fā)現(xiàn)已經(jīng)存在這個(gè)對(duì)象了。
- public enum Language
- {
- CSharp, VisualBasic, Indeterminate
- }
- internal Language DetectLanguage
- {
- get
- {
- string langtype =
- this._view.FormattedLineSource.TextAndAdornmentSequencer.
- SourceBuffer.ContentType.DisplayName;
- if(langtype.Equals("CSHARP",
- StringComparison.InvariantCultureIgnoreCase))
- return Language.CSharp;
- else if(langtype.Equals("BASIC",
- StringComparison.InvariantCultureIgnoreCase))
- return Language.VisualBasic;
- else
- return Language.Indeterminate;
- }
- }
DetectLanguage妥善地利用WPFTextView對(duì)象的FormattedLineSource.TextAndAdornmentSequencer。SourceBuffer.ContentType.DisplayName,這個(gè)屬性告訴我是使用了哪種語言。之后我創(chuàng)建了一個(gè)新的方法PerFormCalculate,用它來解析源代碼,它返回一個(gè)Calculation結(jié)構(gòu)對(duì)象。
第四步:創(chuàng)建 Adornment Factory 類
回到這個(gè)擴(kuò)展,我創(chuàng)建一個(gè)Adornment(InfoBoxAdornmentFactory)的Factory類。這個(gè)類繼承IWpfTextViewCreationListener,用來監(jiān)聽WPF的編輯和創(chuàng)建事件。
- [Export(typeof(IWpfTextViewCreationListener))]
- [ContentType("text")]
- [TextViewRole(PredefinedTextViewRoles.Document)]
- internal sealed class InfoBoxAdornmentFactory : IWpfTextViewCreationListener
- {
- [Export(typeof(AdornmentLayerDefinition))]
- [Name("AlwaysVisibleInfoBox")]
- [Order(After = PredefinedAdornmentLayers.Selection)]
- [TextViewRole(PredefinedTextViewRoles.Interactive)]
- public AdornmentLayerDefinition editorAdornmentLayer = null;
- public void TextViewCreated(IWpfTextView textView)
- {
- new AlwaysVisibleInfoBox(textView);
- }
- }
這里,你可以看到我在這個(gè)類上使用了很多Attributes,像ContentType,它定義了我們只處理文本格式的編輯器;還有TextViewRole,它定義了將被這個(gè)類處理的textview的類型。在這個(gè)類中,我創(chuàng)建了一個(gè)AdornmentLayerDefination對(duì)象。可能你想知道我們沒有使用它,無什么還需要定義它呢,它只是用來配置屬性的。Order屬性指定,當(dāng),InfoBox在層被選之后監(jiān)聽,Name是編輯擴(kuò)展的名字。
第五步:創(chuàng)建Adornment 類
Adornment類實(shí)際創(chuàng)建了一個(gè)WPF用戶控件對(duì)象,并設(shè)置它的視圖畫布。在內(nèi)部構(gòu)造函數(shù)中,我處理IWpfTextView.LayoutChanged事件,當(dāng)代碼修改或者布局改變的時(shí)候,就觸發(fā)這個(gè)事件。
因此,通過這一事件,當(dāng)我們編輯的文檔時(shí),我們可以很容易地得到回調(diào)。當(dāng)瀏覽器編輯器的大小改變時(shí),我還通過處理WPFTextView.ViewportHeightChanged,WPFTextView.ViewportWidthChanged得到回調(diào),使我們可以重新定位相應(yīng)的UserControl。
- public AlwaysVisibleInfoBox(IWpfTextView view)
- {
- _view.LayoutChanged += this.OnLayoutChanged;
- this.GetLayer();
- }
- private void GetLayer()
- {
- _adornmentLayer = this._view.GetAdornmentLayer("AlwaysVisibleInfoBox");
- _view.ViewportHeightChanged += delegate { this.onSizeChange(); };
- _view.ViewportWidthChanged += delegate { this.onSizeChange(); };
- }
- private void OnLayoutChanged(object sender, TextViewLayoutChangedEventArgs e)
- {
- this._info = new CodeInfoTracker(_view);
- this.infobox.UpdateInfo(this._info);
- }
- public void onSizeChange()
- {
- _adornmentLayer.RemoveAllAdornments();
- Canvas.SetLeft(infobox, _view.ViewportRight - 255);
- Canvas.SetTop(infobox, _view.ViewportTop + 10);
- _adornmentLayer.AddAdornment(AdornmentPositioningBehavior.ViewportRelative,
- null, null,
- infobox, null);
- }
因此,構(gòu)造函數(shù)只是調(diào)用GetLayer來獲取的Layer對(duì)象,發(fā)生在ViewportHeightChanged和ViewportWidthChanged ViewPortSizeChage事件。當(dāng)一個(gè)布局改變時(shí),我就能更新這個(gè)用戶的控件。至此,我們成功地建立我們的擴(kuò)展。你可以使用F5運(yùn)行它,它會(huì)打開一個(gè)Visual Studio 2010的Experimental實(shí)例。
安裝和卸載這個(gè)擴(kuò)展:
安裝和卸載這個(gè)擴(kuò)展是非常容易的。當(dāng)您編譯項(xiàng)目后,它會(huì)產(chǎn)生一個(gè)VSIX文件。您可以只需雙擊這個(gè)文件,它會(huì)自動(dòng)安裝到Visual Studio 2010。
文章轉(zhuǎn)自海納百川的博客,
原文地址:http://www.cnblogs.com/zhuqil/archive/2010/04/15/Visual-Studio-Extension.html
【編輯推薦】
- 圖解Visual Studio 2010中的UML建模功能
- 解密中國研發(fā)團(tuán)隊(duì)如何開發(fā)VS2010新特性
- Visual Studio 2010化繁為簡(jiǎn) 令項(xiàng)目管理更輕松
- Visual Studio 2010 Lab Management功能
- Visual Studio 2010將再度擁抱UML