您好,登錄后才能下訂單哦!
今天小編給大家分享一下如何使用模板Editor ViewPort Adornment實現擴展的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
第一步:創建一個Viewport Adornment項目
我們從Extensibility中選擇Viewport Adornment模板創建一個項目。這將生成一個SourceManifest文件和兩個類文件。一個是Adornment類本身,另外一個是AdornmentFactory類。
第二步:添加一個WPF用戶控件
右鍵單擊項目,選擇添加一個新的WPF用戶控件。為了簡單起見,我使用了一個用戶控件。這個用戶控件實際上包含一個Expander控件,設置它的ExpandDirection = Left,它里面又包含了一些TextBlock控件和另外一個Expander ,設置里面的這個Expander的ExpandDirection = Down。看下面的代碼(我刪除不必要的元素,使其更簡單):
<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>
你可以看到,代碼很簡單,兩個Expanders,一個用來顯示基本的統計信息和另外一個顯示擴展的統計信息。我還使用StackPanel來固定TextBlocks布局。現在,如果你看一下后臺代碼,發現它也一樣簡單。其實我已經創建了一個CodeInfoTracker類,用它來為我們分析源代碼文件。我只是為我們的用戶控件添加了一個構造函數,使用戶控件更具擴展性而已。
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; } }
使用了一個結構體Calculators ,這個結構體放置在我們的自定義類中,它有幾個int屬性用來保存分析源文件獲取的所有信息。 info.PerFormCalculate(); 給出分析的結果。這里使用的所有獲取的信息來更新了UIElements。
第三步:創建獲取源文件信息的類
雖然代碼存在一些復雜性,但是這個類其實很簡單。我很感謝CS Parser [^],它幫助我自動地解析源代碼。這個類需要一個IWpfTextView對象,它代表著Visual Studio 2010文本編輯器。實際上WpfTextView實現了IWpfTextView。在執行期間這個類接受這個對象。
我可以從WPFTextView.TextSnapshot.GetText()獲得到了源代碼。在我調用的這個分析的時候,我只需要檢測的代碼是什么語言寫的。開始我想自己來實現,但是感謝上帝,我在WPFTextView中發現已經存在這個對象了。
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對象的FormattedLineSource.TextAndAdornmentSequencer。SourceBuffer.ContentType.DisplayName,這個屬性告訴我是使用了哪種語言。之后我創建了一個新的方法PerFormCalculate,用它來解析源代碼,它返回一個Calculation結構對象。
第四步:創建 Adornment Factory 類
回到這個擴展,我創建一個Adornment(InfoBoxAdornmentFactory)的Factory類。這個類繼承IWpfTextViewCreationListener,用來監聽WPF的編輯和創建事件。
[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); } }
這里,你可以看到我在這個類上使用了很多Attributes,像ContentType,它定義了我們只處理文本格式的編輯器;還有TextViewRole,它定義了將被這個類處理的textview的類型。在這個類中,我創建了一個AdornmentLayerDefination對象。可能你想知道我們沒有使用它,無什么還需要定義它呢,它只是用來配置屬性的。Order屬性指定,當,InfoBox在層被選之后監聽,Name是編輯擴展的名字。
第五步:創建Adornment 類
Adornment類實際創建了一個WPF用戶控件對象,并設置它的視圖畫布。在內部構造函數中,我處理IWpfTextView.LayoutChanged事件,當代碼修改或者布局改變的時候,就觸發這個事件。
因此,通過這一事件,當我們編輯的文檔時,我們可以很容易地得到回調。當瀏覽器編輯器的大小改變時,我還通過處理WPFTextView.ViewportHeightChanged,WPFTextView.ViewportWidthChanged得到回調,使我們可以重新定位相應的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); }
因此,構造函數只是調用GetLayer來獲取的Layer對象,發生在ViewportHeightChanged和ViewportWidthChanged ViewPortSizeChage事件。當一個布局改變時,我就能更新這個用戶的控件。至此,我們成功地建立我們的擴展。你可以使用F5運行它,它會打開一個Visual Studio 2010的Experimental實例。
安裝和卸載這個擴展:
安裝和卸載這個擴展是非常容易的。當您編譯項目后,它會產生一個VSIX文件。您可以只需雙擊這個文件,它會自動安裝到Visual Studio 2010。
以上就是“如何使用模板Editor ViewPort Adornment實現擴展”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。