ContextMenuStrip – Dynamisch Separatoren anzeigen oder ausblenden (C#)

In diesem Artikel möchte ich eine Methode vorstellen mit welcher je nach sichtbaren Menüpunkten eines Kontextmenüs die Separatoren zwischen einzelnen Menügruppen angezeigt (visible == true) bzw ausgeblendet (visibel == false) werden.

Schauen wir uns doch zuerst einmal an um was es dabei wirklich geht.

Hier zuerst das Gesamte Menü mit allen Möglichen Menüpunkten.

Dieses Beispiel stellt das Kontextmenü einer Anwendung dar, die verschiedene Kalendereinträge enthalten kann.

Je nachdem welche Art Kalendereintrag (Planung, Anlieferung, Sperrzeit etc.) ausgewählt wurde und welche Berechtigungen ein Benutzer besitzt werden nur bestimmte Menüpunkte aus dieser Gesamtauswahl angezeigt.

Häufig wird das so geregelt, dass man anstelle die Menüpunkte auszublenden diese nur deaktiviert. In diesem Fall ist es dann nicht notwendig sich Gedanken darüber zu machen einzelne Separatoren für eventuell ganz wegfallende Menügruppen zu entfernen.

Nachfolgend nun einige Abbildungen die anzeigen was passiert wenn man die Menüpunkte ausblendet ohne sich um die Separatoren zu kümmern.

Man beachte die vielen direkt aufeinander folgenden Separatoren, Sieht nicht wirklich Professionell aus.

Nun kann man natürlich die Separatoren ebenfalls im Opening Event manuell Sichtbar oder Unsichtbar machen (setzen der Visible Eigenschaft), dass kann aber je nach Komplexität der Menüstruktur sehr schnell sehr mühsam und sehr fehleranfällig werden.

Genau aus diesem Grund habe ich mir hierzu eine Methode erstellt die sich um diese Aufgabe selbstständig kümmert und je nach sichtbaren Menüpunkten die benötigten Separatoren ebenfalls sichtbar oder unsichtbar macht.

Doch bevor ich die Methode zeige, möchte ich zuerst das Ergebnis anhand der nachfolgenden Abbildungen zeigen. Hier nun die korrekt dargestellten Menüs.

Das sieht doch schon viel besser aus !

So nun aber der Quellcode der Methode.

internal static void SetToolStripSeperatorForContextMenu(ContextMenuStrip contextMenuStrip)
{
	bool isVisible = false;
	int seperatorIndex = 0;
	for (int i = 0; i < contextMenuStrip.Items.Count; i++)
	{
		if (contextMenuStrip.Items[i] is ToolStripSeparator)
		{
			contextMenuStrip.Items[i].Visible = false;
		}

		if (contextMenuStrip.Items[i].Available)
		{
			if (seperatorIndex > 0)
			{
				contextMenuStrip.Items[seperatorIndex].Visible = true;
				seperatorIndex = 0;
			}
			isVisible = true;
		}
		if (contextMenuStrip.Items[i] is ToolStripSeparator)
		{
			if (isVisible)
			{
				seperatorIndex = i;
			}
			isVisible = false;
		}
	}
}

Übrigens die Methode einfach am Ende des Opening Event des Kontextmenüs wie folgt aufrufen.

SetToolStripSeperatorForContextMenu(((ContextMenuStrip) sender));

Und fertig.

Code Optimierung – Teil 1250 (in C# geht auch Spaghetti kodierung)

Ich bin zur Zeit, unter anderem damit beauftragt ein Projekt für einen Kunden zu überarbeiten und zu optimieren.

In diesem Zusammenhang bin ich Heute Morgen auf ein Stück Quellcode gestoßen der mich sofort an die früher (so vor 20 Jahren) sehr üblichen Spaghetti Code Programme erinnert hat.

Ich zeige hier einfach mal den Code dieser Methode wie ich sie vorgefunden habe und anschließend die von mir leicht überarbeitete Methode.

Die Methode wird übrigens dazu verwendet verschiedene Button ein und auszublenden, sowie in Abhängigkeit von Datenfeldern einer Datenbank den Button mit einem Image zu verschönern und entsprechende Datums und Uhrzeiten anzuzeigen oder auszublenden.
Ich denke anhand der nachfolgenden Abbildungen kann man sich ungefähr vorstellen was die Methode macht.

Hier der doch etwas unübersichtliche Code

#region Ankunft

if (entladung.AnkunftLKW.HasValue)
{
	dtpAnkunftDate.Visible = true;
	dtpAnkunftTime.Visible = true;
}
else
{
	dtpAnkunftDate.Visible = false;
	dtpAnkunftTime.Visible = false;
}
#endregion

#region Einfahrt

if (entladung.EinfahrtLKW.HasValue)
{
	dtpEinfahrtDate.Visible = true;
	dtpEinfahrtTime.Visible = true;
}
else
{
	dtpEinfahrtDate.Visible = false;
	dtpEinfahrtTime.Visible = false;
}

#endregion

#region Entladung Start

if (entladung.EntladeStart.HasValue)
{
	dtpEntladungStartDate.Visible = true;
	dtpEntladungStartTime.Visible = true;
	btnEntladungStart.ImageIndex = 0;
	if (entladung.EntladeEnde.HasValue)
	{
		btnEntladungStart.Enabled = false;
	}
	else
	{
		btnEntladungStart.Enabled = true;
	}
}
else
{
	dtpEntladungStartDate.Visible = false;
	dtpEntladungStartTime.Visible = false;
}

#endregion

#region Entlade Ende

if (entladung.EntladeEnde.HasValue)
{
	dtpEntladungEndeDate.Visible = true;
	dtpEntladungEndeTime.Visible = true;
	btnEntladungEnde.ImageIndex = 0;

	btnEntladungEnde.Enabled = !entladung.AusfahrtLKW.HasValue;
}
 else
{
	if (entladung.EntladeStart.HasValue)
	{
		btnEntladungEnde.Enabled = true;
	}
	else
	{
		btnEntladungEnde.Enabled = false;
		btnEntladungEnde.ImageIndex = -1;
	}

	dtpEntladungEndeDate.Visible = false;
	dtpEntladungEndeTime.Visible = false;

}

#endregion

#region Ausfahrt

if (entladung.AusfahrtLKW.HasValue)
{
	dtpAusfahrtDate.Visible = true;
	dtpAusfahrtTime.Visible = true;
}
else
{
	dtpAusfahrtDate.Visible = false;
	dtpAusfahrtTime.Visible = false;
}

#endregion

Hier der Optimierte Code

dtpAnkunftDate.Visible = entladung.AnkunftLKW.HasValue;
dtpAnkunftTime.Visible = entladung.AnkunftLKW.HasValue;

dtpEinfahrtDate.Visible = entladung.EinfahrtLKW.HasValue;
dtpEinfahrtTime.Visible = entladung.EinfahrtLKW.HasValue;

dtpEntladungStartDate.Visible = entladung.EntladeStart.HasValue;
dtpEntladungStartTime.Visible = entladung.EntladeStart.HasValue;

dtpEntladungEndeDate.Visible = entladung.EntladeEnde.HasValue;
dtpEntladungEndeTime.Visible = entladung.EntladeEnde.HasValue;

dtpAusfahrtDate.Visible = entladung.AusfahrtLKW.HasValue;
dtpAusfahrtTime.Visible = entladung.AusfahrtLKW.HasValue;

btnEntladungStart.ImageIndex = entladung.EntladeStart.HasValue ? 0 : -1;

btnEntladungStart.Enabled = ((!entladung.EntladeStart.HasValue) |
						((entladung.EntladeStart.HasValue && !entladung.EntladeEnde.HasValue)));

btnEntladungEnde.ImageIndex = entladung.EntladeEnde.HasValue ? 0 : -1;

btnEntladungEnde.Enabled = (entladung.EntladeStart.HasValue && !entladung.AusfahrtLKW.HasValue);

Man beachte die Zeilenzahlen. Die obere Variante hat genau die 4 fache Anzahl Code.
Obwohl, schön aussehen tun die vielen If’s und Else schon 🙂

Und da der untere Code viel kürzer und einfacher ist, braucht man auch nichts mehr mit Region umklammern.

c# – Splitt Container Collapse Panel Advanced Example – WinForm

In einem aktuellen Projekt hat sich der Kunde gewünscht, ein „platzsparendes“ Winform, zur Anzeige von Kalenderinformationen, zu erhalten. Und da der Wunsch des Kunden gleich einem Befehl ist…. 🙂 Voila !

Hier (m)ein Lösungsansatz.

Und da ich denke, dass auch im Zeitalter von WPF, noch immer WinForm Anwendungen erstellt werden, veröffentliche ich diesen Lösungsansatz (der übrigens schon in einigen Projekten eingesetzt wird und nicht ganz neu ist) hier in diesem Beitrag und hoffe dass dies dem einen oder anderen auch Heute noch dabei behilflich sein kann, ein ähnliches Problem so einfacher lösen zu können.
Wer das Beispiel 1 : 1 in einem eigenen Projekt verwenden möchte:

Bitte schön !!!

Hier kurz noch einmal die Aufgabenstellung:
Die Form soll auf der linken Seite ein Calendar Month Control enthalten und auf der rechten Seite ein TabControl enthalten, welches dann ein komplexes Calendar Control (ähnlich wie Outlook Kalender) enthält.
Und genau da kommt wohl auch der Wunsch her, dass man das Calendar Month Control ausblenden und einblenden kann.

Eigentlich ….
gar nicht so aufwendig, aber ….
Wenn man das ganze umsetzen will, stößt man doch recht schnell an die „einfachen“ Grenzen der verfügbaren Controls.

Zur Demonstration, dass es doch nicht so aufwendig ist, habe ich dieses kleine Beispiel erstellt, welches man auch als VS2010 Projekt am Ende des Beitrags herunterladen kann.

Außer, dass man, die benötigten Controls in der richtigen Reihenfolge auf das Form ziehen muss (Siehe im Source Code) benötigt man nur ein paar Zeilen, den ich nachfolgend Kurz zeigen möchte.

namespace WinFormSplittContainerAdvancedExample
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            splitContainerRight.Panel1Collapsed = true;
        }

        private void btnHideLeftPanel_Click(object sender, EventArgs e)
        {
            splitContainerMain.Panel1Collapsed = true;
            panelShow.Visible = true;
            splitContainerRight.Panel1Collapsed = false;
        }

        private void btnShowLeftPanel_Click(object sender, EventArgs e)
        {
            splitContainerMain.Panel1Collapsed = false;
            panelShow.Visible = false;
            splitContainerRight.Panel1Collapsed = true;
        }
    }
}

Und so sieht das ganze im laufenden Betrieb aus:

Hier der Screenshot mit angezeigtem linken Kalender Panel

Und hier der Screenshot mit ausgeblendetem linken Kalender Panel

Und hier der Download: WinFormSplittContainerAdvancedExample (Einfach ZIP File entpacken und mit Visual Studio 2010 öffenen.

Viel Spaß!!

c# – tabControl – tabPage – Fehlende Visible Eigenschaft

Wer in WinForms Anwendungen das tabControl einsetzt wird über kurz oder lang darüber stolpern, dass die tabPage Controls keine Visible Eigenschaft besitzen.

Das bedeute es ist weder in der Entwicklungsumgebung noch zur Laufzeit Möglich einfach durch setzen der Visible Eigenschaft einzelne tabPage Seiten zwischen sichtbar und unsichtbar umzuschalten.

Hier daher ein kleines Code Snippet mit dem man die tabPage aus dem Programmcode heraus aus der tabPage Auflistung des tabControls entfernen oder hinzufügen kann.

// Hier der Code für Visible=False
tabControlOptionen.TabPages.Remove(tabUser);

// Hier der Code für Visible=True
tabControlOptionen.TabPages.Add(tabUser);

TabPageVisibleHideDemo