Erweitern der Fenster "Eigenschaften", "Aufgabenliste", "Ausgabe" und "Optionen"

Sie können auf jedes Toolfenster in Visual Studio zugreifen. In dieser exemplarischen Vorgehensweise wird gezeigt, wie Sie Informationen zu Ihrem Toolfenster in eine neue Seite "Optionen " und eine neue Einstellung auf der Seite "Eigenschaften " integrieren und in die Fenster "Aufgabenliste " und "Ausgabe " schreiben.

Erstellen einer Erweiterung mit einem Toolfenster

  1. Erstellen Sie ein Projekt namens TodoList mithilfe der VSIX-Vorlage, und fügen Sie eine benutzerdefinierte Toolfensterelementvorlage namens TodoWindow hinzu.

    Hinweis

    Weitere Informationen zum Erstellen einer Erweiterung mit einem Toolfenster finden Sie unter Erstellen einer Erweiterung mit einem Toolfenster.

Einrichten des Toolfensters

Fügen Sie ein Textfeld hinzu, in das ein neues ToDo-Element eingegeben werden soll, eine Schaltfläche zum Hinzufügen des neuen Elements zur Liste und ein ListBox-Element zum Anzeigen der Elemente in der Liste.

  1. Löschen Sie in TodoWindow.xaml die Steuerelemente "Button", "TextBox" und "StackPanel" aus "UserControl".

    Hinweis

    Dadurch wird der button1_Click-Ereignishandler nicht gelöscht, den Sie in einem späteren Schritt wiederverwenden werden.

  2. Ziehen Sie im Abschnitt "Alle WPF-Steuerelemente" der Toolbox ein Canvas-Steuerelement auf das Raster.

  3. Ziehen Sie ein TextBox-Steuerelement, eine Schaltfläche und ein ListBox-Steuerelement auf den Zeichenbereich. Ordnen Sie die Elemente so an, dass sich das TextBox- und die Schaltfläche auf derselben Ebene befinden, und das ListBox-Element füllt den Rest des darunter liegenden Fensters aus, wie in der abbildung unten dargestellt.

    Finished Tool Window

  4. Suchen Sie im XAML-Bereich die Schaltfläche, und legen Sie dessen Inhaltseigenschaft auf "Hinzufügen" fest. Verbinden Sie den Schaltflächenereignishandler erneut mit dem Button-Steuerelement, indem Sie ein Click="button1_Click" Attribut hinzufügen. Der Canvas-Block sollte wie folgt aussehen:

    <Canvas HorizontalAlignment="Left" Width="306">
        <TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="10,10,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="208"/>
            <Button x:Name="button" Content="Add" HorizontalAlignment="Left" Margin="236,13,0,0" VerticalAlignment="Top" Width="48" Click="button1_Click"/>
            <ListBox x:Name="listBox" HorizontalAlignment="Left" Height="222" Margin="10,56,0,0" VerticalAlignment="Top" Width="274"/>
    </Canvas>
    

Anpassen des Konstruktors

  1. Fügen Sie in der Datei "TodoWindowControl.xaml.cs " die folgende Direktive hinzu:

    using System;
    
  2. Fügen Sie einen öffentlichen Verweis auf todoWindow hinzu, und der TodoWindowControl-Konstruktor verwendet einen TodoWindow-Parameter. Der Code sollte wie folgt aussehen:

    public TodoWindow parent;
    
    public TodoWindowControl(TodoWindow window)
    {
        InitializeComponent();
        parent = window;
    }
    
  3. Ändern Sie in TodoWindow.cs todoWindowControl-Konstruktor, um den TodoWindow-Parameter einzuschließen. Der Code sollte wie folgt aussehen:

    public TodoWindow() : base(null)
    {
        this.Caption = "TodoWindow";
        this.BitmapResourceID = 301;
        this.BitmapIndex = 1;
    
         this.Content = new TodoWindowControl(this);
    }
    

Seite "Optionen" erstellen

Sie können eine Seite im Dialogfeld "Optionen " bereitstellen, damit Benutzer Einstellungen für das Toolfenster ändern können. Zum Erstellen einer Optionsseite ist eine Klasse erforderlich, die die Optionen und einen Eintrag in der Datei "TodoListPackage.cs" oder "TodoListPackage.vb" beschreibt.

  1. Fügen Sie eine Klasse namens ToolsOptions.cshinzu. Übernehmen Sie die ToolsOptions Klasse von DialogPage.

    class ToolsOptions : DialogPage
    {
    }
    
  2. Fügen Sie die folgende Using-Direktive hinzu:

    using Microsoft.VisualStudio.Shell;
    
  3. Die Seite "Optionen" in dieser exemplarischen Vorgehensweise enthält nur eine Option namens "DaysAhead". Fügen Sie der Klasse ein privates Feld mit dem Namen "daysAhead" und eine Eigenschaft mit dem ToolsOptions Namen "DaysAhead" hinzu:

    private double daysAhead;
    
    public double DaysAhead
    {
        get { return daysAhead; }
        set { daysAhead = value; }
    }
    

    Jetzt müssen Sie das Projekt auf dieser Seite "Optionen" aufmerksam machen.

Die Seite "Optionen" für Benutzer verfügbar machen

  1. Fügen Sie in TodoWindowPackage.cs der Klasse eine ProvideOptionPageAttribute hinzu TodoWindowPackage :

    [ProvideOptionPage(typeof(ToolsOptions), "ToDo", "General", 101, 106, true)]
    
  2. Der erste Parameter für den ProvideOptionPage-Konstruktor ist der Typ der Klasse ToolsOptions, die Sie zuvor erstellt haben. Der zweite Parameter , "ToDo", ist der Name der Kategorie im Dialogfeld "Optionen ". Der dritte Parameter , "General", ist der Name der Unterkategorie des Dialogfelds "Optionen", in dem die Seite "Optionen " verfügbar ist. Die nächsten beiden Parameter sind Ressourcen-IDs für Zeichenfolgen; der erste ist der Name der Kategorie, und der zweite ist der Name der Unterkategorie. Der letzte Parameter bestimmt, ob mithilfe der Automatisierung auf diese Seite zugegriffen werden kann.

    Wenn ein Benutzer Ihre Seite "Optionen" öffnet, sollte er wie in der folgenden Abbildung dargestellt sein.

    Options Page

    Beachten Sie die Kategorie "ToDo " und die Unterkategorie "Allgemein".

Daten für die Eigenschaftenfenster verfügbar machen

Sie können ToDo-Listeninformationen verfügbar machen, indem Sie eine Klasse mit dem Namen TodoItem erstellen, die Informationen zu den einzelnen Elementen in der ToDo-Liste speichert.

  1. Fügen Sie eine Klasse namens TodoItem.cshinzu.

    Wenn das Toolfenster für Benutzer verfügbar ist, werden die Elemente im ListBox-Objekt durch TodoItems dargestellt. Wenn der Benutzer eines dieser Elemente im ListBox-Steuerelement auswählt, werden im Eigenschaftenfenster Informationen zum Element angezeigt.

    Um Daten im Eigenschaftenfenster verfügbar zu machen, wandeln Sie die Daten in öffentliche Eigenschaften mit zwei speziellen Attributen umCategory. Description Description ist der Text, der unten im Eigenschaftenfenster angezeigt wird. Category bestimmt, wo die Eigenschaft angezeigt werden soll, wenn das Eigenschaftenfenster in der Kategorisierten Ansicht angezeigt wird. In der folgenden Abbildung befindet sich das Eigenschaftenfenster in der Kategorisierten Ansicht, die Name-Eigenschaft in der Kategorie "ToDo-Felder " ist ausgewählt, und die Beschreibung der Eigenschaft "Name " wird unten im Fenster angezeigt.

    Properties Window

  2. Fügen Sie die folgende Using-Direktiven der Datei "TodoItem.cs " hinzu.

    using System.ComponentModel;
    using System.Windows.Forms;
    using Microsoft.VisualStudio.Shell.Interop;
    
  3. Fügen Sie der Klassendeklaration den public Zugriffsmodifizierer hinzu.

    public class TodoItem
    {
    }
    

    Fügen Sie die beiden Eigenschaften Name und DueDate. Wir werden dies UpdateList() und CheckForErrors() später tun.

    public class TodoItem
    {
        private TodoWindowControl parent;
        private string name;
        [Description("Name of the ToDo item")]
        [Category("ToDo Fields")]
        public string Name
        {
            get { return name; }
            set
            {
                name = value;
                parent.UpdateList(this);
            }
        }
    
        private DateTime dueDate;
        [Description("Due date of the ToDo item")]
        [Category("ToDo Fields")]
        public DateTime DueDate
        {
            get { return dueDate; }
            set
            {
                dueDate = value;
                parent.UpdateList(this);
                parent.CheckForErrors();
            }
        }
    }
    
  4. Fügen Sie dem Benutzersteuerelement einen privaten Verweis hinzu. Fügen Sie einen Konstruktor hinzu, der das Benutzersteuerelement und den Namen für dieses ToDo-Element akzeptiert. Um den Wert für daysAheadzu finden, ruft er die Options-Seiteneigenschaft ab.

    private TodoWindowControl parent;
    
    public TodoItem(TodoWindowControl control, string itemName)
    {
        parent = control;
        name = itemName;
        dueDate = DateTime.Now;
    
        double daysAhead = 0;
        IVsPackage package = parent.parent.Package as IVsPackage;
        if (package != null)
        {
            object obj;
            package.GetAutomationObject("ToDo.General", out obj);
    
            ToolsOptions options = obj as ToolsOptions;
            if (options != null)
            {
                daysAhead = options.DaysAhead;
            }
        }
    
        dueDate = dueDate.AddDays(daysAhead);
    }
    
  5. Da Instanzen der TodoItem Klasse im ListBox-Objekt gespeichert werden und das ListBox die ToString Funktion aufruft, müssen Sie die ToString Funktion überladen. Fügen Sie den folgenden Code zu TodoItem.cs nach dem Konstruktor und vor dem Ende der Klasse hinzu.

    public override string ToString()
    {
        return name + " Due: " + dueDate.ToShortDateString();
    }
    
  6. Fügen Sie in TodoWindowControl.xaml.cs Stubmethoden zur Klasse für die TodoWindowControlCheckForError und UpdateList methoden hinzu. Platzieren Sie sie nach processDialogChar und vor dem Ende der Datei.

    public void CheckForErrors()
    {
    }
    public void UpdateList(TodoItem item)
    {
    }
    

    Die CheckForError Methode ruft eine Methode auf, die denselben Namen im übergeordneten Objekt hat, und diese Methode überprüft, ob Fehler aufgetreten sind und diese ordnungsgemäß behandeln. Die UpdateList Methode aktualisiert das ListBox-Steuerelement im übergeordneten Steuerelement. Die Methode wird aufgerufen, wenn sich die Name Und DueDate Eigenschaften in dieser Klasse ändern. Sie werden später implementiert.

Integration in die Eigenschaftenfenster

Schreiben Sie nun den Code, der das ListBox-Objekt verwaltet, das mit dem Eigenschaftenfenster verknüpft ist.

Sie müssen den Schaltflächenklickhandler ändern, um das TextBox-Objekt zu lesen, ein TodoItem-Objekt zu erstellen und es dem ListBox-Objekt hinzufügt.

  1. Ersetzen Sie die vorhandene button1_Click Funktion durch Code, der ein neues TodoItem-Objekt erstellt, und fügt sie dem ListBox-Objekt hinzu. Es wird aufgerufen TrackSelection(), die später definiert wird.

    private void button1_Click(object sender, RoutedEventArgs e)
    {
        if (textBox.Text.Length > 0)
        {
            var item = new TodoItem(this, textBox.Text);
            listBox.Items.Add(item);
            TrackSelection();
            CheckForErrors();
        }
    }
    
  2. Wählen Sie in der Entwurfsansicht das ListBox-Steuerelement aus. Klicken Sie im Eigenschaftenfenster auf die Schaltfläche "Ereignishandler" , und suchen Sie das SelectionChanged-Ereignis . Füllen Sie das Textfeld mit listBox_SelectionChanged aus. Dadurch wird ein Stub für einen SelectionChanged-Handler hinzugefügt und dem Ereignis zugewiesen.

  3. Implementieren Sie die TrackSelection()-Methode. Da Sie die SVsUIShellSTrackSelection Dienste abrufen müssen, müssen Sie die GetService Barrierefreiheit durch todoWindowControl vornehmen. Fügen Sie der TodoWindow-Klasse die folgende Methode hinzu:

    internal object GetVsService(Type service)
    {
        return GetService(service);
    }
    
  4. Fügen Sie die folgenden Using-Direktiven zu TodoWindowControl.xaml.cs hinzu:

    using System.Runtime.InteropServices;
    using Microsoft.VisualStudio.Shell.Interop;
    using Microsoft.VisualStudio;
    using Microsoft.VisualStudio.Shell;
    
  5. Füllen Sie den SelectionChanged-Handler wie folgt aus:

    private void listBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        TrackSelection();
    }
    
  6. Füllen Sie nun die TrackSelection-Funktion aus, die die Integration mit dem Eigenschaftenfenster bereitstellt. Diese Funktion wird aufgerufen, wenn der Benutzer dem ListBox-Element ein Element hinzufügt oder auf ein Element im ListBox-Objekt klickt. Er fügt den Inhalt des ListBox-Steuerelements einem SelectionContainer hinzu und übergibt den SelectionContainer an den Ereignishandler des EigenschaftenfenstersOnSelectChange. Der TrackSelection-Dienst verfolgt ausgewählte Objekte auf der Benutzeroberfläche nach und zeigt deren Eigenschaften an.

    private SelectionContainer mySelContainer;
    private System.Collections.ArrayList mySelItems;
    private IVsWindowFrame frame = null;
    
    private void TrackSelection()
    {
        if (frame == null)
        {
            var shell = parent.GetVsService(typeof(SVsUIShell)) as IVsUIShell;
            if (shell != null)
            {
                var guidPropertyBrowser = new
                Guid(ToolWindowGuids.PropertyBrowser);
                shell.FindToolWindow((uint)__VSFINDTOOLWIN.FTW_fForceCreate,
                ref guidPropertyBrowser, out frame);
            }
        }
        if (frame != null)
            {
                frame.Show();
            }
        if (mySelContainer == null)
        {
            mySelContainer = new SelectionContainer();
        }
    
        mySelItems = new System.Collections.ArrayList();
    
        var selected = listBox.SelectedItem as TodoItem;
        if (selected != null)
        {
            mySelItems.Add(selected);
        }
    
        mySelContainer.SelectedObjects = mySelItems;
    
        ITrackSelection track = parent.GetVsService(typeof(STrackSelection))
                                as ITrackSelection;
        if (track != null)
        {
            track.OnSelectChange(mySelContainer);
        }
    }
    

    Nachdem Sie nun über eine Klasse verfügen, die im Eigenschaftenfenster verwendet werden kann, können Sie das Eigenschaftenfenster in das Toolfenster integrieren. Wenn der Benutzer im Toolfenster auf ein Element im ListBox-Fenster klickt, sollte das Eigenschaftenfenster entsprechend aktualisiert werden. Ebenso sollte das zugeordnete Element aktualisiert werden, wenn der Benutzer ein ToDo-Element im Eigenschaftenfenster ändert.

  7. Fügen Sie nun den rest des UpdateList-Funktionscodes in TodoWindowControl.xaml.cs hinzu. Es sollte das geänderte TodoItem aus dem ListBox-Element ablegen und erneut hinzufügen.

    public void UpdateList(TodoItem item)
    {
        var index = listBox.SelectedIndex;
        listBox.Items.RemoveAt(index);
        listBox.Items.Insert(index, item);
        listBox.SelectedItem = index;
    }
    
  8. Testen Sie Ihren Code. Erstellen Sie das Projekt, und starten Sie das Debugging. Die experimentelle Instanz sollte angezeigt werden.

  9. Öffnen Sie die Seite "Extras>Optionen". Im linken Bereich sollte die Kategorie "ToDo" angezeigt werden. Kategorien werden alphabetisch aufgelistet, sehen Sie sich also unter den Ts an.

  10. Auf der Seite "Todo-Optionen " sollte die DaysAhead Eigenschaft auf 0 festgelegt sein. Ändern Sie sie in 2.

  11. Öffnen Sie im Menü "Ansicht/ Andere Fenster" TodoWindow. Geben Sie "EndDate " in das Textfeld ein, und klicken Sie auf "Hinzufügen".

  12. Im Listenfeld sollte ein Datum angezeigt werden, das zwei Tage später als heute ist.

Hinzufügen von Text zum Ausgabefenster und elementen zur Aufgabenliste

Für die Aufgabenliste erstellen Sie ein neues Objekt vom Typ "Task", und fügen Sie das Task-Objekt dann der Aufgabenliste hinzu, indem Sie dessen Add Methode aufrufen. Wenn Sie in das Ausgabefenster schreiben möchten, rufen Sie dessen GetPane Methode auf, um ein Bereichsobjekt abzurufen, und rufen dann die OutputString Methode des Bereichsobjekts auf.

  1. Fügen Sie in TodoWindowControl.xaml.cs in der button1_Click Methode Code hinzu, um den Bereich "Allgemein " des Ausgabefensters abzurufen (die Standardeinstellung ist), und schreiben Sie ihn. Die Methode sollte wie folgt aussehen:

    private void button1_Click(object sender, EventArgs e)
    {
        if (textBox.Text.Length > 0)
        {
            var item = new TodoItem(this, textBox.Text);
            listBox.Items.Add(item);
    
            var outputWindow = parent.GetVsService(
                typeof(SVsOutputWindow)) as IVsOutputWindow;
            IVsOutputWindowPane pane;
            Guid guidGeneralPane = VSConstants.GUID_OutWindowGeneralPane;
            outputWindow.GetPane(ref guidGeneralPane, out pane);
            if (pane != null)
            {
                 pane.OutputString(string.Format(
                    "To Do item created: {0}\r\n",
                 item.ToString()));
        }
            TrackSelection();
            CheckForErrors();
        }
    }
    
  2. Um der Aufgabenliste Elemente hinzuzufügen, müssen Sie der TodoWindowControl-Klasse eine geschachtelte Klasse hinzufügen. Die geschachtelte Klasse muss von TaskProvider. Fügen Sie den folgenden Code am Ende der TodoWindowControl Klasse hinzu.

    [Guid("72de1eAD-a00c-4f57-bff7-57edb162d0be")]
    public class TodoWindowTaskProvider : TaskProvider
    {
        public TodoWindowTaskProvider(IServiceProvider sp)
            : base(sp)
        {
        }
    }
    
  3. Fügen Sie als Nächstes einen privaten Verweis auf TodoTaskProvider die TodoWindowControl Klasse und eine CreateProvider() Methode hinzu. Der Code sollte wie folgt aussehen:

    private TodoWindowTaskProvider taskProvider;
    private void CreateProvider()
    {
        if (taskProvider == null)
        {
            taskProvider = new TodoWindowTaskProvider(parent);
            taskProvider.ProviderName = "To Do";
        }
    }
    
  4. Fügen Sie ClearError()der Klasse einen Eintrag hinzu, TodoWindowControl der die Aufgabenliste löscht, und ReportError()fügen Sie der Klasse einen Eintrag hinzu.

    private void ClearError()
    {
        CreateProvider();
        taskProvider.Tasks.Clear();
    }
    private void ReportError(string p)
    {
        CreateProvider();
        var errorTask = new Task();
        errorTask.CanDelete = false;
        errorTask.Category = TaskCategory.Comments;
        errorTask.Text = p;
    
        taskProvider.Tasks.Add(errorTask);
    
        taskProvider.Show();
    
        var taskList = parent.GetVsService(typeof(SVsTaskList))
            as IVsTaskList2;
        if (taskList == null)
        {
            return;
        }
    
        var guidProvider = typeof(TodoWindowTaskProvider).GUID;
         taskList.SetActiveProvider(ref guidProvider);
    }
    
  5. Implementieren Sie nun die CheckForErrors Methode wie folgt.

    public void CheckForErrors()
    {
        foreach (TodoItem item in listBox.Items)
        {
            if (item.DueDate < DateTime.Now)
            {
                ReportError("To Do Item is out of date: "
                    + item.ToString());
            }
        }
    }
    

Ausprobieren

  1. Erstellen Sie das Projekt, und starten Sie das Debugging. Die experimentelle Instanz wird geöffnet.

  2. Öffnen Sie todoWindow (Andere Windows>TodoWindow anzeigen>).

  3. Geben Sie etwas in das Textfeld ein, und klicken Sie dann auf "Hinzufügen".

    Dem Listenfeld wird ein Fälligkeitsdatum von 2 Tagen nach dem heutigen Tag hinzugefügt. Es werden keine Fehler generiert, und die Vorgangsliste (Vorgangsliste anzeigen>) sollte keine Einträge enthalten.

  4. Ändern Sie nun die Einstellung auf der Seite "Extras>Optionen>ToDo" von 2 zurück auf 0.

  5. Geben Sie etwas anderes in todoWindowein, und klicken Sie dann erneut auf "Hinzufügen". Dadurch wird ein Fehler und auch ein Eintrag in der Aufgabenliste ausgelöst.

    Beim Hinzufügen von Elementen wird das Anfangsdatum auf jetzt plus 2 Tage festgelegt.

  6. Klicken Sie im Menü "Ansicht " auf "Ausgabe ", um das Ausgabefenster zu öffnen.

    Beachten Sie, dass jedes Mal, wenn Sie ein Element hinzufügen, eine Meldung im Aufgabenlistenbereich angezeigt wird.

  7. Klicken Sie auf eines der Elemente im ListBox-Steuerelement.

    Im Eigenschaftenfenster werden die beiden Eigenschaften für das Element angezeigt.

  8. Ändern Sie eine der Eigenschaften, und drücken Sie dann die EINGABETASTE.

    Das Element wird im ListBox-Objekt aktualisiert.