Estendere le finestre Proprietà, Elenco attività, Output e Opzioni

È possibile accedere a qualsiasi finestra degli strumenti in Visual Studio. Questa procedura dettagliata illustra come integrare le informazioni sulla finestra degli strumenti in una nuova pagina Opzioni e una nuova impostazione nella pagina Proprietà e come scrivere nelle finestre Elenco attività e Output.

Creare un'estensione con una finestra degli strumenti

  1. Creare un progetto denominato TodoList usando il modello VSIX e aggiungere un modello di elemento della finestra degli strumenti personalizzato denominato TodoWindow.

    Nota

    Per altre informazioni sulla creazione di un'estensione con una finestra degli strumenti, vedere Creare un'estensione con una finestra degli strumenti.

Configurare la finestra degli strumenti

Aggiungere un controllo TextBox in cui digitare un nuovo elemento ToDo, un pulsante per aggiungere il nuovo elemento all'elenco e un controllo ListBox per visualizzare gli elementi nell'elenco.

  1. In TodoWindow.xaml eliminare i controlli Button, TextBox e StackPanel da UserControl.

    Nota

    In questo modo non viene eliminato il gestore eventi button1_Click , che verrà riutilizzato in un passaggio successivo.

  2. Dalla sezione Tutti i controlli WPF della casella degli strumenti trascinare un controllo Canvas nella griglia.

  3. Trascinare un controllo TextBox, un controllo Button e un controllo ListBox nell'area di disegno. Disporre gli elementi in modo che TextBox e Button siano sullo stesso livello e listBox riempia il resto della finestra sottostante, come nell'immagine seguente.

    Finished Tool Window

  4. Nel riquadro XAML trovare il pulsante e impostarne la proprietà Content su Aggiungi. Riconnettere il gestore eventi del pulsante al controllo Button aggiungendo un Click="button1_Click" attributo. Il blocco Canvas dovrebbe essere simile al seguente:

    <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>
    

Personalizzare il costruttore

  1. Nel file TodoWindowControl.xaml.cs aggiungere la direttiva using seguente:

    using System;
    
  2. Aggiungere un riferimento pubblico a TodoWindow e fare in modo che il costruttore TodoWindowControl prenda un parametro TodoWindow. Il codice dovrebbe essere simile al seguente:

    public TodoWindow parent;
    
    public TodoWindowControl(TodoWindow window)
    {
        InitializeComponent();
        parent = window;
    }
    
  3. In TodoWindow.cs modificare il costruttore TodoWindowControl per includere il parametro TodoWindow. Il codice dovrebbe essere simile al seguente:

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

Creare una pagina Opzioni

È possibile specificare una pagina nella finestra di dialogo Opzioni in modo che gli utenti possano modificare le impostazioni per la finestra degli strumenti. La creazione di una pagina Opzioni richiede sia una classe che descrive le opzioni e una voce nel file TodoListPackage.cs o TodoListPackage.vb .

  1. Aggiungere una classe denominata ToolsOptions.cs. Fare in modo che la ToolsOptions classe erediti da DialogPage.

    class ToolsOptions : DialogPage
    {
    }
    
  2. Aggiungere la direttiva using seguente:

    using Microsoft.VisualStudio.Shell;
    
  3. Nella pagina Opzioni di questa procedura dettagliata è disponibile una sola opzione denominata DaysAhead. Aggiungere un campo privato denominato daysAhead e una proprietà denominata DaysAhead alla ToolsOptions classe :

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

    È ora necessario rendere il progetto consapevole di questa pagina Opzioni.

Rendere disponibile agli utenti la pagina Opzioni

  1. In TodoWindowPackage.cs aggiungere un oggetto ProvideOptionPageAttribute alla TodoWindowPackage classe :

    [ProvideOptionPage(typeof(ToolsOptions), "ToDo", "General", 101, 106, true)]
    
  2. Il primo parametro del costruttore ProvideOptionPage è il tipo della classe ToolsOptions, creata in precedenza. Il secondo parametro, "ToDo", è il nome della categoria nella finestra di dialogo Opzioni . Il terzo parametro, "Generale", è il nome della sottocategoria della finestra di dialogo Opzioni in cui sarà disponibile la pagina Opzioni. I due parametri successivi sono ID risorsa per le stringhe; il primo è il nome della categoria e il secondo è il nome della sottocategoria. Il parametro finale determina se è possibile accedere a questa pagina usando l'automazione.

    Quando un utente apre la pagina Opzioni, dovrebbe essere simile all'immagine seguente.

    Options Page

    Si noti la categoria ToDo e la sottocategoria Generale.

Rendere disponibili i dati al Finestra Proprietà

È possibile rendere disponibili le informazioni sull'elenco ToDo creando una classe denominata TodoItem che archivia informazioni sui singoli elementi nell'elenco ToDo.

  1. Aggiungere una classe denominata TodoItem.cs.

    Quando la finestra degli strumenti è disponibile per gli utenti, gli elementi in ListBox saranno rappresentati da TodoItems. Quando l'utente seleziona uno di questi elementi in ListBox, nella finestra Proprietà verranno visualizzate informazioni sull'elemento.

    Per rendere disponibili i dati nella finestra Proprietà , si trasformano i dati in proprietà pubbliche con due attributi speciali e DescriptionCategory. Description è il testo visualizzato nella parte inferiore della finestra Proprietà . Category determina la posizione in cui deve essere visualizzata la proprietà quando viene visualizzata la finestra Proprietà nella visualizzazione Categorizzata . Nell'immagine seguente, la finestra Proprietà è in visualizzazione Categorizzata , la proprietà Name nella categoria ToDo Fields è selezionata e la descrizione della proprietà Name viene visualizzata nella parte inferiore della finestra.

    Properties Window

  2. Aggiungere le direttive using seguenti al file TodoItem.cs .

    using System.ComponentModel;
    using System.Windows.Forms;
    using Microsoft.VisualStudio.Shell.Interop;
    
  3. Aggiungere il public modificatore di accesso alla dichiarazione di classe.

    public class TodoItem
    {
    }
    

    Aggiungere le due proprietà e NameDueDate. Lo faremo UpdateList() e CheckForErrors() in seguito.

    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. Aggiungere un riferimento privato al controllo utente. Aggiungere un costruttore che accetta il controllo utente e il nome per questo elemento ToDo. Per trovare il valore per daysAhead, ottiene la proprietà della pagina Opzioni.

    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. Poiché le istanze della TodoItem classe verranno archiviate in ListBox e ListBox chiamerà la ToString funzione , è necessario eseguire l'overload della ToString funzione. Aggiungere il codice seguente a TodoItem.cs, dopo il costruttore e prima della fine della classe.

    public override string ToString()
    {
        return name + " Due: " + dueDate.ToShortDateString();
    }
    
  6. In TodoWindowControl.xaml.cs aggiungere metodi stub alla TodoWindowControl classe per i CheckForError metodi e UpdateList . Inserirli dopo ProcessDialogChar e prima della fine del file.

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

    Il CheckForError metodo chiamerà un metodo con lo stesso nome nell'oggetto padre e tale metodo verificherà se si sono verificati errori e li gestiranno correttamente. Il metodo aggiornerà ListBox nel controllo padre. Il UpdateList metodo viene chiamato quando cambiano le Name proprietà e DueDate in questa classe. Verranno implementati in un secondo momento.

Eseguire l'integrazione nel Finestra Proprietà

Scrivere ora il codice che gestisce listBox, che verrà associato alla finestra Proprietà .

È necessario modificare il gestore di clic del pulsante per leggere textBox, creare un oggetto TodoItem e aggiungerlo al controllo ListBox.

  1. Sostituire la funzione esistente button1_Click con il codice che crea un nuovo Oggetto TodoItem e lo aggiunge a ListBox. TrackSelection()Chiama , che verrà definito in un secondo momento.

    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. Nella visualizzazione Progettazione selezionare il controllo ListBox. Nella finestra Proprietà fare clic sul pulsante Gestori eventi e trovare l'evento SelectionChanged. Compilare la casella di testo con listBox_SelectionChanged. In questo modo viene aggiunto uno stub per un gestore SelectionChanged e lo assegna all'evento.

  3. Implementa il metodo TrackSelection(). Poiché è necessario ottenere i SVsUIShellSTrackSelection servizi, è necessario rendere GetService accessibile da TodoWindowControl. Aggiungere il metodo seguente alla classe TodoWindow:

    internal object GetVsService(Type service)
    {
        return GetService(service);
    }
    
  4. Aggiungere le direttive using seguenti a TodoWindowControl.xaml.cs:

    using System.Runtime.InteropServices;
    using Microsoft.VisualStudio.Shell.Interop;
    using Microsoft.VisualStudio;
    using Microsoft.VisualStudio.Shell;
    
  5. Compilare il gestore SelectionChanged come indicato di seguito:

    private void listBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        TrackSelection();
    }
    
  6. Compilare ora la funzione TrackSelection, che fornirà l'integrazione con la finestra Proprietà . Questa funzione viene chiamata quando l'utente aggiunge un elemento a ListBox o fa clic su un elemento nel controllo ListBox. Aggiunge il contenuto di ListBox a un oggetto SelectionContainer e passa SelectionContainer al gestore eventi della OnSelectChange finestra Proprietà. Il servizio TrackSelection tiene traccia degli oggetti selezionati nell'interfaccia utente e visualizza le relative proprietà

    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);
        }
    }
    

    Ora che si dispone di una classe che può essere usata dalla finestra Proprietà , è possibile integrare la finestra Proprietà con la finestra degli strumenti. Quando l'utente fa clic su un elemento nella casella di riepilogo nella finestra degli strumenti, la finestra Proprietà deve essere aggiornata di conseguenza. Analogamente, quando l'utente modifica un elemento ToDo nella finestra Proprietà , l'elemento associato deve essere aggiornato.

  7. Aggiungere ora il resto del codice della funzione UpdateList in TodoWindowControl.xaml.cs. Deve eliminare e riaggiungere l'oggetto TodoItem modificato da ListBox.

    public void UpdateList(TodoItem item)
    {
        var index = listBox.SelectedIndex;
        listBox.Items.RemoveAt(index);
        listBox.Items.Insert(index, item);
        listBox.SelectedItem = index;
    }
    
  8. Testare il codice. Compilare il progetto e avviare il debug. Verrà visualizzata l'istanza sperimentale.

  9. Aprire la pagina Opzioni strumenti>. Verrà visualizzata la categoria ToDo nel riquadro sinistro. Le categorie sono elencate in ordine alfabetico, quindi guarda sotto le T.

  10. Nella pagina Opzioni todo dovrebbe essere visualizzata la DaysAhead proprietà impostata su 0. Impostarlo su 2.

  11. Nel menu Visualizza/Altre finestre aprire TodoWindow. Digitare EndDate nella casella di testo e fare clic su Aggiungi.

  12. Nella casella di riepilogo dovrebbe essere visualizzata una data due giorni dopo rispetto a oggi.

Aggiungere testo alla finestra Output ed elementi all'elenco attività

Per l'elenco attività, si crea un nuovo oggetto di tipo Task e quindi si aggiunge tale oggetto Task all'elencoattività chiamando il relativo Add metodo. Per scrivere nella finestra Output , chiamare il GetPane relativo metodo per ottenere un oggetto riquadro e quindi chiamare il OutputString metodo dell'oggetto riquadro.

  1. Nel metodo TodoWindowControl.xaml.csbutton1_Click aggiungere il codice per ottenere il riquadro Generale della finestra Output (che è l'impostazione predefinita) e scrivervi. Il metodo dovrebbe essere simile al seguente:

    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. Per aggiungere elementi all'elenco attività, è necessario aggiungere una classe annidata alla classe TodoWindowControl. La classe nidificata deve derivare da TaskProvider. Aggiungere il codice seguente alla fine della TodoWindowControl classe .

    [Guid("72de1eAD-a00c-4f57-bff7-57edb162d0be")]
    public class TodoWindowTaskProvider : TaskProvider
    {
        public TodoWindowTaskProvider(IServiceProvider sp)
            : base(sp)
        {
        }
    }
    
  3. Aggiungere quindi un riferimento privato a TodoTaskProvider e un CreateProvider() metodo alla TodoWindowControl classe . Il codice dovrebbe essere simile al seguente:

    private TodoWindowTaskProvider taskProvider;
    private void CreateProvider()
    {
        if (taskProvider == null)
        {
            taskProvider = new TodoWindowTaskProvider(parent);
            taskProvider.ProviderName = "To Do";
        }
    }
    
  4. Aggiungere ClearError(), che cancella l'elenco attività e ReportError(), che aggiunge una voce all'elenco attività, alla TodoWindowControl classe .

    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. Implementare ora il CheckForErrors metodo , come indicato di seguito.

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

Prova

  1. Compilare il progetto e avviare il debug. Viene visualizzata l'istanza sperimentale.

  2. Aprire TodoWindow (Visualizza>altre finestre>TodoWindow).

  3. Digitare qualcosa nella casella di testo e quindi fare clic su Aggiungi.

    Una data di scadenza di 2 giorni dopo oggi viene aggiunta alla casella di riepilogo. Non vengono generati errori e l'elenco attività (visualizza>elenco attività) non deve contenere voci.

  4. Modificare ora l'impostazione nella pagina Opzioni>strumenti>ToDo da 2 a 0.

  5. Digitare qualcos'altro in TodoWindow e quindi fare di nuovo clic su Aggiungi . In questo modo viene attivato un errore e anche una voce nell'elenco attività.

    Quando si aggiungono elementi, la data iniziale viene impostata su ora più 2 giorni.

  6. Scegliere Output dal menu Visualizza per aprire la finestra Output.

    Si noti che ogni volta che si aggiunge un elemento, viene visualizzato un messaggio nel riquadro Elenco attività.

  7. Fare clic su uno degli elementi in ListBox.

    Nella finestra Proprietà vengono visualizzate le due proprietà per l'elemento.

  8. Modificare una delle proprietà e quindi premere INVIO.

    L'elemento viene aggiornato in ListBox.