• 0

[C#] IComponentChangeService, ISelectionService & IDesignerHost


Question

I'm doing this custom user control, I'm also working with designers and I need to use the Interfaces described in the topic subject. But I have a little situation. If any of those interfaces are not initialized somewhere in the code (ie: IComponentChangeService ICCS = (IComponentChangeService)GetService(typeof(IComponentChangeService))), I get an exception. But, I'm using these interfaces in lots of places in the code and in different classes, one of them doesn't even allow me to use the "GetService" method, it says it is not available in this context.

So, I'm looking for a way, to initialize these 3 interfaces just once and be able to use them everywhere I want. But I'm not being successful, how can I accomplish that?

Link to comment
Share on other sites

12 answers to this question

Recommended Posts

  • 0

You need to take advantage of the controls Site property, as this is should only be assigned in Design-mode.

public class MyTestComponet : UserControl
{
	private Container components = null;
	private IComponentChangeService changeService = null;
	private ISelectionService selectionService = null;
	private Button button = null;

	public MyTestComponent() { InitializeComponent(); }

	private void InitializeComponent()
	{
		this.button = new Button();
		this.SuspendLayout();

		this.button.Location = new System.Drawing.Point(24, 16);
		this.button.Name = "button";
		this.button.Size = new System.Drawing.Size(50, 20);
		this.button.TabIndex = 0;

		this.Controls.AddRange(new Control[] { this.button });
		this.Name = "MyTestComponent";
		this.Size = new System.Drawing.Size(400, 300);
		this.ResumeLayout(false);
	}

	/// <summary>
	/// When the control is sited (which only occurs in Design-mode), we can create our references to the service instances for this class.
	/// </summary>
	public override ISite Site
	{
		get { return base.Site; }
		set
		{
			ClearChangeNotifications();
			ClearSelectionNotifications();
			base.Site = value;

			if (base.Site == null)
				return;

			changeService = (IComponentChangeService)GetService(typeof(IComponentChangeService));
			RegisterChangeNotifications();

			selectionService = (ISelectionService)GetService(typeof(ISelectionService));
			RegisterSelectionNotifications();
		}
	}

	private void ClearChangeNotifications()
	{
		changeService = (IComponentChangeService)GetService(typeof(IComponentChangeService));

		if (changeService != null)
		{
			changeService.ComponentChanged -= new ComponentChangedEventHandler(OnComponentChanged);
			changeService.ComponentChanged -= new ComponentChangingEventHandler(OnComponentChanging);
			changeService.ComponentAdded -= new ComponentEventHandler(OnComponentAdded);
			changeService.ComponentAdding -= new ComponentEventHandler(OnComponentAdding);
			changeService.ComponentRemoved -= new ComponentEventHandler(OnComponentRemoved);
			changeService.ComponentRemoving -= new ComponentEventHandler(OnComponentRemoving);
			changeService.ComponentRename -= new ComponentRenameEventHandler(OnComponentRename);
		}
	}

	private void ClearSelectionNotifications()
	{
		selectionService = (ISelectionService)GetService(typeof(ISelectionService));

		if (selectionService != null)
		{
			selectionService.SelectionChanged -= new EventHandler(OnSelectionChanged);
			selectionService.SelectionChanging -= new EventHandler(OnSelectionChanging);
		}
	}

	private void RegisterChangeNotifications()
	{
		if (changeService != null)
		{
			changeService.ComponentChanged += new ComponentChangedEventHandler(OnComponentChanged);
			changeService.ComponentChanged += new ComponentChangingEventHandler(OnComponentChanging);
			changeService.ComponentAdded += new ComponentEventHandler(OnComponentAdded);
			changeService.ComponentAdding += new ComponentEventHandler(OnComponentAdding);
			changeService.ComponentRemoved += new ComponentEventHandler(OnComponentRemoved);
			changeService.ComponentRemoving += new ComponentEventHandler(OnComponentRemoving);
			changeService.ComponentRename += new ComponentRenameEventHandler(OnComponentRename);
		}
	}

	private void RegisterSelectionNotifications()
	{		
		if (selectionService != null)
		{
			selectionService.SelectionChanged += new EventHandler(OnSelectionChanged);
			selectionService.SelectionChanging += new EventHandler(OnSelectionChanging);
		}
	}

	private void OnComponentChanged(object sender, ComponentChangedEventArgs e)
	{

	}

	private void OnComponentChanging(object sender, ComponentChangingEventArgs e)
	{

	}

	private void OnComponentAdded(object sender, ComponentEventArgs e)
	{

	}

	private void OnComponentAdding(object sender, ComponentEventArgs e)
	{

	}

	private void OnComponentRemoved(object sender, ComponentEventArgs e)
	{

	}

	private void OnComponentRemoving(object sender, ComponentEventArgs e)
	{

	}

	private void OnComponentRename(object sender, ComponentRenameEventArgs e)
	{

	}

	private void OnSelectionChanged(object sender, EventArgs e)
	{

	}

	private void OnSelectionChanging(object sender, EventArgs e)
	{

	}

	protected override void Dispose(bool disposing)
	{
		if (disposing)
		{
			ClearChangeNotifications();
			ClearSelectionNotifications();

			if (components != null)
				components.Dispose();
		}
		base.Dispose(disposing);
	}
}

This was adapted from a couple of MSDN articles, which should really be your first port of call.

Link to comment
Share on other sites

  • 0

That got me a bit confused... That's a lot of code, I tried just this:

public partial class PageStrip : UserControl
{
	public override ISite Site
	{
		get { return base.Site; }
		set {
			base.Site = value;

			if (base.Site == null) return;

			Global.ICCS = (IComponentChangeService)GetService(typeof(IComponentChangeService));
			Global.ISS = (ISelectionService)GetService(typeof(ISelectionService));
			Global.IDH = (IDesignerHost)GetService(typeof(IDesignerHost));
		}
	}
}

(Global is a internal static class and ICCS, ISS, IDH are internal static properties)

Using all my current code (my final UC is almost done, just finishing some bugs) and the code I just posted above using your suggestion, seems to be working. I used to get some exceptions when I tried to initialize those services only once on other parts of the code but doing them on ISite seems to be working.

Is there something wrong using it that way? As I've never used ISite, I don't understand it much.

Link to comment
Share on other sites

  • 0

The ISite interface (contract) is for binding a component to a container. Is there any reason you need to access these services outside of your user control?

Link to comment
Share on other sites

  • 0

I don't think so... I only need them for a couple of things:

- I'm using smart-tags/actionlists, one action creates some controls inside my user control (my control has toolstrip, it will create buttons in the toolstirp at design time when clicked on the action) - ICCS and IDH

- Be able to, at design time, select some components (the buttons inside the toolstrip) - ISS

- I'm handling the the OnSelectionChanged and OnComponentRemoving methods in the designer for a couple of things that need to be done when they are called.

Basically, I'm using the services only inside my control, and most of them, inside the designer class.

Is it ok then, what I did?

Link to comment
Share on other sites

  • 0

I'm sorry if I sounded harsh, that was not the intention.

The thing is, you helped me to solve my problem on post #3 and my final code, teh solution to my problem in my current project is on post #4. I just want to know if "my solution" in post #4 is ok, if it doesn't have any problems using it that way. Like I said, I never used ISite nor knew about it since you helped me here and I just want to know if my approach is fine or if I shouldn't do it that way for some odd reason. That's all I want to know.

I really appreciate your help on this issue here, no one else could solve this issue for me and you did. I'm really thankful, really.

Link to comment
Share on other sites

  • 0

I was not exactly taking about ISite but more the way I coded this:

"Global is a internal static class and ICCS, ISS, IDH are internal static properties"

These properties check if they are null, if they are, then I set the service for them, otherwise, I don't need to set them again.

I believe it's no problem but I just wanted your opinion on that.

Link to comment
Share on other sites

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.