Multiple Duplicate Events

Hi,

I have added a texture path handler to my rhino plugin as shown below. It works as expected on the ContentAdded event. When I change the texture on a material, the ContentChanged event if triggered four times. I am not able to understand the reason.

@dale

TexturePathHandler

using System;
using System.IO;
using System.Text;
using Rhino.Render;
using Rhino;
using Rhino.UI;

namespace Hero.Handlers
{

    public class TexturePathHandler
    {
        public TexturePathHandler()
        {
        }

        private static void ValidateMaterial(object sender, RenderContentEventArgs e)
        {
            // When a material is added to the document, check if any of the texture files are not sourced from the P: drive.
            // Give a warning if this is the case.
            if (e.Content is RenderMaterial material && !ValidateTexturePaths(material))
            {
                StringBuilder sb = new StringBuilder();
                sb.AppendLine($"Material: {material.Name}");
                sb.AppendLine();
                sb.AppendLine("Has one or more texture files that are not sourced from a project folder on P: drive.");
                sb.AppendLine();
                sb.AppendLine("This is against the recommended best practice.");

                Dialogs.ShowMessage(sb.ToString(), "Bad Texture");
            }
        }

        private static bool ValidateTexturePaths(RenderMaterial material)
        {

            // Get the possible child slots for the material. These child slots are essentially filled by the Texture objects.
            RenderMaterial.StandardChildSlots[] slots = (RenderMaterial.StandardChildSlots[])Enum.GetValues(typeof(RenderMaterial.StandardChildSlots));

            // Get the texture for each of the child slots and check if the texture path starts with "P:".
            foreach (RenderMaterial.StandardChildSlots slot in slots)
            {
                RenderTexture texture = material.GetTextureFromUsage(slot);
                if (texture == null)
                {
                    continue;
                }
                string texturePath = texture.Filename;
                if (!texturePath.StartsWith("P:"))
                {
                    return false;
                }
            }
            return true;
        }

        public void Start()
        {
            RenderContent.ContentAdded += ValidateMaterial;
            RenderContent.ContentChanged += ValidateMaterial;
        }

        public void Stop()
        {
            RenderContent.ContentAdded -= ValidateMaterial;
            RenderContent.ContentChanged -= ValidateMaterial;
        }

    }
}

Plugin

using System;
using System.IO;
using System.Text;
using System.Windows;
using Rhino;
using Rhino.PlugIns;
using Hero.Handlers;

namespace Hero
{
    public class HeroPlugIn : PlugIn
    {
        public override PlugInLoadTime LoadTime => PlugInLoadTime.AtStartup;
        private readonly TexturePathHandler _texturePathHandler;

        public HeroPlugIn()
        {
            Instance = this;
            _texturePathHandler = new TexturePathHandler();
        }

        public static HeroPlugIn Instance { get; private set; }

        protected override LoadReturnCode OnLoad(ref string errorMessage)
        {
            _texturePathHandler.Start();
            return LoadReturnCode.Success;
        }

        protected override void OnShutdown()
        {
            _texturePathHandler.Stop();
        }
    }
}

I guess I should try doing this check directly on a texture being added rather than the material. That way I will have to listen to just one event.