2

I am currently working on a visual studio package project in C#, that provides a new tool window to store and copy custom code snippets.

So far, I designed the little window as follow:

Overview about the graphical design

The XAML code for the window is:

<TreeView Name="tevTemplates" Background="#00000000">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Items}">
            <StackPanel Orientation="Horizontal">
                <Image Margin="0,0,5,0" Source="{Binding Image}" />
                <TextBlock Text="{Binding Title}" />
            </StackPanel>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

And the custom data model I use:

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Drawing;

namespace Sago.TemQWindow.Classes
{
    /// <summary>
    /// Represents a simple data item to display easy an item inside a view
    /// </summary>
    public class MenuNode
    {
        /// <summary>
        /// Initializes a new instance of a Sago.TemQWindow.Classes.MenuNode object with the display title
        /// </summary>
        /// <param name="title"></param>
        public MenuNode(string title) : this(title, null) { }

        /// <summary>
        /// Initializes a new instance of a Sago.TemQWindow.Classes.MenuNode object with the display title and image
        /// </summary>
        /// <param name="title"></param>
        /// <param name="image"></param>
        public MenuNode(string title, Image image)
        {
            this.Items = new ObservableCollection<MenuNode>();
            Title = title;
            Image = image;
        }

        /// <summary>
        /// Gets or sets the display title
        /// </summary>
        public string Title { get; set; }

        /// <summary>
        /// Gets or sets the display image
        /// </summary>
        public Image Image { get; set; }

        /// <summary>
        /// Gets or sets the sub items of the node
        /// </summary>
        public ObservableCollection<MenuNode> Items { get; set; }
    }
}

After opening the tool window the following source code loads the content and sub directory contents of the template folder:

/// <summary>
/// Loads the whole folder structure of the given path recursive
/// </summary>
private void LoadStructure(MenuNode rootNode, string path)
{
    // Gets all files
    string[] files = IO.Directory.GetFiles(path);
    foreach (string file in files)
    {
        // Creates and adds the sub node for all files inside the given folder
        string clearName = IO.Path.GetFileNameWithoutExtension(file);
        MenuNode node = new MenuNode(clearName);
        rootNode.Items.Add(node);
    }
    // Gets all sub directories
    string[] directories = IO.Directory.GetDirectories(path);
    foreach (string directory in directories)
    {
        // Creates and adds the sub directory as a sub node
        string clearName = IO.Path.GetFileNameWithoutExtension(directory);
        MenuNode node = new MenuNode(clearName);
        rootNode.Items.Add(node);

        // Calls the method recursive
        LoadStructure(node, directory);
    }
}

In the next step, I want to visualize the folders and files within the treeview control with the specific images. As you can see, I already implemented the image propety inside the data model and XAML binding.

Now the problem is that I don't know, how I add these images to the project and access them over the code. As i already researched the visual studio package project don't have the possibility to access to the Properties.Resources content.

I would be very grateful if someone could help me with this problem.

Sago
  • 75
  • 8

1 Answers1

0

One way of doing this would be like this.

Step 1: Change the XAML to use monikers

<ResourceDictionary ... 
    xmlns:imaging="clr-namespace:Microsoft.VisualStudio.Imaging;assembly=Microsoft.VisualStudio.Imaging">

<TreeView Name="tevTemplates" Background="#00000000">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate ItemsSource="{Binding Items}">
            <StackPanel Orientation="Horizontal">
                <imaging:CrispImage Moniker="{Binding Image}" />
                <TextBlock Text="{Binding Title}" />
            </StackPanel>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

Step 2: Change the Model to use monikers

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Drawing;

using Microsoft.VisualStudio.Imaging.Interop;

namespace Sago.TemQWindow.Classes
{
    /// <summary>
    /// Represents a simple data item to display easy an item inside a view
    /// </summary>
    public class MenuNode
    {
        ...

        /// <summary>
        /// Gets or sets the display image
        /// </summary>
        public ImageMoniker Image { get; set; }

        ...
    }
}

Step 3: Set monikers

private void LoadStructure(MenuNode rootNode, string path)
{
    // Gets all files
    string[] files = IO.Directory.GetFiles(path);
    foreach (string file in files)
    {
        // Creates and adds the sub node for all files inside the given folder
        string clearName = IO.Path.GetFileNameWithoutExtension(file);
        MenuNode node = new MenuNode(clearName);
        node.Image = KnownMonikers.TextFile;
        rootNode.Items.Add(node);
    }
    // Gets all sub directories
    string[] directories = IO.Directory.GetDirectories(path);
    foreach (string directory in directories)
    {
        // Creates and adds the sub directory as a sub node
        string clearName = IO.Path.GetFileNameWithoutExtension(directory);
        MenuNode node = new MenuNode(clearName);
        node.Image = KnownMonikers.FolderClosed;
        rootNode.Items.Add(node);

        // Calls the method recursive
        LoadStructure(node, directory);
    }
}

Check here for all KnownMonikers: Visual Studio's KnownMonikers

sboulema
  • 837
  • 1
  • 10
  • 22