溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何使用模板Editor ViewPort Adornment實現(xiàn)擴(kuò)展

發(fā)布時間:2022-03-31 14:19:41 來源:億速云 閱讀:167 作者:iii 欄目:編程語言

今天小編給大家分享一下如何使用模板Editor ViewPort Adornment實現(xiàn)擴(kuò)展的相關(guān)知識點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。

第一步:創(chuàng)建一個Viewport Adornment項目

我們從Extensibility中選擇Viewport Adornment模板創(chuàng)建一個項目。這將生成一個SourceManifest文件和兩個類文件。一個是Adornment類本身,另外一個是AdornmentFactory類。

第二步:添加一個WPF用戶控件

右鍵單擊項目,選擇添加一個新的WPF用戶控件。為了簡單起見,我使用了一個用戶控件。這個用戶控件實際上包含一個Expander控件,設(shè)置它的ExpandDirection = Left,它里面又包含了一些TextBlock控件和另外一個Expander ,設(shè)置里面的這個Expander的ExpandDirection = Down??聪旅娴拇a(我刪除不必要的元素,使其更簡單):

<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,一個用來顯示基本的統(tǒng)計信息和另外一個顯示擴(kuò)展的統(tǒng)計信息。我還使用StackPanel來固定TextBlocks布局?,F(xiàn)在,如果你看一下后臺代碼,發(fā)現(xiàn)它也一樣簡單。其實我已經(jīng)創(chuàng)建了一個CodeInfoTracker類,用它來為我們分析源代碼文件。我只是為我們的用戶控件添加了一個構(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;  }  }

使用了一個結(jié)構(gòu)體Calculators ,這個結(jié)構(gòu)體放置在我們的自定義類中,它有幾個int屬性用來保存分析源文件獲取的所有信息。 info.PerFormCalculate(); 給出分析的結(jié)果。這里使用的所有獲取的信息來更新了UIElements。

第三步:創(chuàng)建獲取源文件信息的類

雖然代碼存在一些復(fù)雜性,但是這個類其實很簡單。我很感謝CS Parser [^],它幫助我自動地解析源代碼。這個類需要一個IWpfTextView對象,它代表著Visual Studio 2010文本編輯器。實際上WpfTextView實現(xiàn)了IWpfTextView。在執(zhí)行期間這個類接受這個對象。

我可以從WPFTextView.TextSnapshot.GetText()獲得到了源代碼。在我調(diào)用的這個分析的時候,我只需要檢測的代碼是什么語言寫的。開始我想自己來實現(xiàn),但是感謝上帝,我在WPFTextView中發(fā)現(xiàn)已經(jīng)存在這個對象了。

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,這個屬性告訴我是使用了哪種語言。之后我創(chuàng)建了一個新的方法PerFormCalculate,用它來解析源代碼,它返回一個Calculation結(jié)構(gòu)對象。

第四步:創(chuàng)建 Adornment Factory 類

回到這個擴(kuò)展,我創(chuàng)建一個Adornment(InfoBoxAdornmentFactory)的Factory類。這個類繼承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);  }  }

這里,你可以看到我在這個類上使用了很多Attributes,像ContentType,它定義了我們只處理文本格式的編輯器;還有TextViewRole,它定義了將被這個類處理的textview的類型。在這個類中,我創(chuàng)建了一個AdornmentLayerDefination對象。可能你想知道我們沒有使用它,無什么還需要定義它呢,它只是用來配置屬性的。Order屬性指定,當(dāng),InfoBox在層被選之后監(jiān)聽,Name是編輯擴(kuò)展的名字。

第五步:創(chuàng)建Adornment 類

Adornment類實際創(chuàng)建了一個WPF用戶控件對象,并設(shè)置它的視圖畫布。在內(nèi)部構(gòu)造函數(shù)中,我處理IWpfTextView.LayoutChanged事件,當(dāng)代碼修改或者布局改變的時候,就觸發(fā)這個事件。

因此,通過這一事件,當(dāng)我們編輯的文檔時,我們可以很容易地得到回調(diào)。當(dāng)瀏覽器編輯器的大小改變時,我還通過處理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對象,發(fā)生在ViewportHeightChanged和ViewportWidthChanged ViewPortSizeChage事件。當(dāng)一個布局改變時,我就能更新這個用戶的控件。至此,我們成功地建立我們的擴(kuò)展。你可以使用F5運(yùn)行它,它會打開一個Visual Studio 2010的Experimental實例。

安裝和卸載這個擴(kuò)展:

安裝和卸載這個擴(kuò)展是非常容易的。當(dāng)您編譯項目后,它會產(chǎn)生一個VSIX文件。您可以只需雙擊這個文件,它會自動安裝到Visual Studio 2010。

如何使用模板Editor ViewPort Adornment實現(xiàn)擴(kuò)展

以上就是“如何使用模板Editor ViewPort Adornment實現(xiàn)擴(kuò)展”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學(xué)習(xí)更多的知識,請關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI