Laden...

Customcontrol Dropdownlist

Erstellt von AlfameisterT vor 18 Jahren Letzter Beitrag vor 18 Jahren 1.756 Views
A
AlfameisterT Themenstarter:in
154 Beiträge seit 2005
vor 18 Jahren
Customcontrol Dropdownlist

Hallo,

ich habe ein Cutomcontrol abgeleitet von der Dropdownlist erstellt.

Das Problem ist jetzt, das nach einem Postback der SelectedValue nicht aktuallisiert wird. Gesetzt wird der manuel in der Render Methode mit HTML-Code 'selected="selected"'.

Wenn der Wert nicht automatisch zurückgelesen wird (Control ist ja von Dropdownlist abgeleitet), wo muss ich da ansetzten um diesen Wert zu bekommen?

#
88 Beiträge seit 2005
vor 18 Jahren

Hast du mal versucht den SelectedValue in der PageLoad Methode auszulesen?

4.506 Beiträge seit 2004
vor 18 Jahren

Hallo AlfameisterT,

hast Du Dir Grundlagen zu dem Thema CustomControl angeeignet? Das läuft nicht so selbstständig wie man das erwartet. Ich sitze jetzt gerade nicht an meinem Entwicklungs-PC, ansonsten könnte ich Dir mal eine kleine Beispiel-Einführungstutorial-Solution zukommen lassen, die aufzeigt, wie CustomControls zu verwenden sind.

Grob erklärt, musst Du selbst nach einem PostBack entscheiden, was für Änderungen übernommen werden, und welche verworfen werden. Das hat den entscheidenden Vorteil, dass man gleich eine Validierung mit vornehmen kann. Aber alles muss mit einem CC selbst deklariert werden. Ereignisse, PostBack-Veränderungen ...

Vielleicht kannst Du aber auch ein UserControl nehmen, die sind am Anfang deutlich einfacher zu verwenden...

Ciao
Norman-Timo

A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”

A
AlfameisterT Themenstarter:in
154 Beiträge seit 2005
vor 18 Jahren

Erstmal Danke für die Hilfe.
Die Grundlagen sind mir schon klar (so halbwegs 😉 ). Deshalb auch das Customcontrol statt Usercontrol.
Da das Control von einem bestehenden Control abgeleitet ist, hätte das alles funktionieren müssen. Es wurde ja nur die Render Methode angepasst.

Grund war folgender. Es ist wichtig wie der HTML Code aufgebaut ist.

Der Tag 'Name' muss aus 'this.UniqueID' bestehen.
Der Tag 'Id' muss aus 'this.ClientID' besetehen.

Weiterhin muss der Code erst das enthalten was das Basiscontrol generiert hätte, danach kann man eigene Elemente einfügen.

Z.B.
Basiscontrol generiert <option value="10">test</option>

Dies würde ein Problem verursachen <option title="huhu" value="10">test</option>

Sorum gehts <option value="10" title="huhu" >test</option>

.

4.506 Beiträge seit 2004
vor 18 Jahren

Guten Morgen zusammen,

wie versprochen sende ich mal hier ein Einführungsbeispiel von mir entworfen, damit die Zusammenhänge, insbesondere die Notwendigkeit der beiden Interfaces IPostBackEventHandler und IPostBackDataHandler sowie deren Handhabung...

Es sollte alles aus den Kommentarzeilen zu lesen zu sein. Am Besten mal durch-Debuggen, dann sieht man, was passiert 😉

Vielleicht hilfts❔


using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Collections.Specialized;
using System.ComponentModel;

namespace MyWebLibrary
{
	/// <summary>
	/// Dies ist ein Beispiel für ein Custom Control. Es enthält die Basics für die Post-Daten-Auswertungen und die
	/// Implementierung eigener Events, die von der Anzeige-Seite an dieses Control weitergereicht werden.
	/// </summary>
	/// <remarks>
	/// Implementiert die beiden Interdaces 'IPostBackEventHandler' und 'IPostBackDataHandler', die dafür sorgen, dass
	/// Methoden eingeführt werden, die zwingend für die Event- und Post-Datenverarbeitung notwendig sind.
	/// </remarks>
	[DefaultProperty("Text"), ToolboxData("<{0}:WebCustomControl1 runat=server></{0}:WebCustomControl1>")]
	public class WebCustomControl1 : System.Web.UI.WebControls.WebControl , IPostBackEventHandler, IPostBackDataHandler
	{
		/* Das Attribut '[DefaultProperty("Text"), ToolboxData("<{0}:WebCustomControl1 runat=server></{0}:WebCustomControl1>")]'
		 * sorgt dafür, dass dieses Control ein Standard-Property enthält ("text"). Für nähere Details zum Standard-Property
		 * siehe MSDN. Weiterhin enthält es das Attribut ToolboxData, das nix weiteres macht, als die Anzeige festlegt,
		 * während das Control auf die Designer-Fläche im VisualStudio gezogen wurde.
		*/

		// Ein paar Variablen, weiterhin eine Textbox, Button und eine Checkbox, die in dem Control anezeigt werden.
		private string text;
		private HtmlInputButton button = new HtmlInputButton();
		private HtmlInputText txtField = new HtmlInputText();
		private HtmlInputCheckBox chkBox = new HtmlInputCheckBox();

		// Ein delegate, das für das eigene Event-Handling sozusagen den "Stempel" enthält. Jeder der das eigene Event
		// abonnieren möchte muss eine Methode anbinden, die dieser Delegate-Struktur entspricht. Hier Rückgabewert void
		// und KEINE Parameter.
		public delegate void myDelegate();

		// Definiere ein Event mit dem Namen Click und gib diesem den "Stempel" myDelegate.
		public event myDelegate Click;
		// Definiere ein Event TextChanged und gib diesem den "Stempel" System.EventHandler, das eine Methode erfordert,
		// die keinen Rückgabewert hat und die Parameter 'object' und 'System.EventArgs' erwartet.
		public event System.EventHandler TextChanged;


		/// <summary>
		/// Property Text, das Standard Property sein soll. Es werden die Attribute Bindable, Category und DefaultValue
		/// angegeben.
		/// </summary>
		/// <remarks>
		/// Bindable-> hierzu sagt die MSDN, und ich kanns nicht besser erklären:
		/// "
		/// If a property has been marked with the BindableAttribute constructor of the value true, then a property
		/// change notification should be raised for that property. This means that if Bindable is Yes, then two-way
		/// data binding is supported. If Bindable is No, you can still bind to the property, but it should not be shown
		/// in the default set of properties to bind to, because it might or might not raise a property change
		/// notification.
		/// "
		/// 
		/// Category-> Dieses Attribut gibt dem Property eine Kategorie, für eine Aufzählung, siehe MSDN. Z.B. ist es
		/// möglich einem Property die Kategorie 'Design' zu geben, das dann festlegt, dass das Property im VisualStudio
		/// auch rechts unten im Designer zu sehen ist, und somit zur Entwurfszeit schon zugriffsfähig ist.
		/// 
		/// DefaultValue-> Das dürfte wohl für sich sprechen ;-)
		/// </remarks>
		[Bindable(true), Category("Appearance"), DefaultValue("")]
		public string Text
		{
			get
			{
				return text;
			}

			set
			{
				text = value;
			}
		}

		/// <summary>
		/// Das ist die Initialisierungsphase, wie z.B. im Vergleich zu "normalen" Init-Phasen in einer ASPX-Seite. Bei
		/// richtiger Anwendung wird in der Anzeige-Seite dieses Control in der Initialisierungsphase initialisiert.
		/// Daraufhin springt der Rechner in diese Methode, damit auch dieses Control die Chance hat "seine" Controls
		/// zu initialisieren, das für dessen eigene Anzeige benötigt wird.
		/// </summary>
		/// <param name="e">Wird nur weitergereicht an base.OnInit, und nicht speziell verwendet.</param>
		protected override void OnInit(EventArgs e)
		{
			// Definiere mir den Button näher. UNBEDINGT ID vergeben!!!
			button.ID = "btnTest";
			button.Name = "btnTest";
			button.Value = "Drück mich";
			// Definiert mir ein Post-Back-Ereignis bei 'onClick' (im HTML-Tag).
			button.Attributes.Add("onClick", this.Page.GetPostBackEventReference(button, "btn"));

			// Definiere mir mein Textfeld näher. UNBEDINGT ID vergeben!!!
			txtField.ID="txtField";
			// Definiert mir ein Post-Back-Ereignis bei 'onchanged' (im HTML-Tag).
			txtField.Attributes.Add("onchanged", this.Page.GetPostBackEventReference(txtField, "txt"));


			// man kann auch auf die Page (Anzeige-Seite) zurückgreifen mittels 'this.Page'
			if (this.Page.IsPostBack)
			{
				txtField.Value = Convert.ToString(this.Page.Session["txtField"]);
			}


			// Registriere Event-Weiterleitung und Post-Daten-Weiterleitung bei der Anzeige-Seite
			this.Page.RegisterRequiresRaiseEvent(this);
			this.Page.RegisterRequiresPostBack(this);
			
			base.OnInit (e);
		}


		/// <summary>
		/// Diese Methode wird aufgerufen, wenn wir entscheiden, dass das Ereignis 'Click' eingetreten ist (siehe weiter
		/// unten). Die Methode ruft dann, sofern vorhanden, ALLE registrierten Methoden auf. (Alle Abonennten eines
		/// Ereignisses müssen eine Methode hinterlegen, die hier aufgerufen wird.)
		/// </summary>
		/// <param name="e">Nicht benutzt hier.</param>
		private void OnClick(EventArgs e)
		{
			if (Click != null)
			{
				Click();
			}
		}

		/// <summary>
		/// Diese Methode wird aufgerufen, wenn wir entscheiden, dass das Ereignis 'TextChanged' eingetreten ist (siehe
		/// weiter unten). Die Methode ruft dann, sofern vorhanden, ALLE registrierten Methoden auf. (Alle Abonennten
		/// eines Ereignisses müssen eine Methode hinterlegen, die hier aufgerufen wird.)
		/// </summary>
		/// <param name="e">Weitergereicht an das System.EventArgs, das im "Stempel" vorgegeben war.</param>
		private void OnTextChanged(EventArgs e)
		{
			// Stelle fest, ob sich überhaupt jemand für das Ereignis registriert hat, ansonsten tue nix.
			if (TextChanged != null)
			{
				TextChanged(null, e);
			}
		}

		/// <summary>
		/// Registriert einen Click auf das Control an sich. Also wenn der Benutzer auf das CustomControl, und NICHT
		/// auf ein darin enthaltenes Control, wie der Button oder die CheckBox, klickt (z.B. auf die Hintergrund-
		/// fläche. (Es könnte aber möglich sein, dass ein Klick auf ein darin enthaltenes Control trotzdem zusätzlich
		/// dazu führt, dass der Rechner hier hinein findet (ungetestet)).
		/// </summary>
		private void WebCustomControl1_Click()
		{
			string test = "Stop!";
		}
		
		/// <summary>
		/// Original Beschriftung: Define the method of IPostBackEventHandler that raises change events.
		/// Diese Methode wird aufgerufen, wenn ein Standard-Control, das mit diesem CustomControl gezeichnet wurde,
		/// ein Event auslöst. Z.B. der Button wirft bei einem Click ein Click-Ereignis, das zunächst bei der Anzeige-
		/// Seite landet. Habe ich zuvor Event-Weiterleitung bei meiner Anzeige-Seite registriert (mittels
		/// this.Page.RegisterRequiresRaiseEvent(this);), dann wird diese Methode aufgerufen.
		/// </summary>
		/// <param name="eventArgument">Dieser Parameter definiert mir der Auslöser. Dieses muss bei der Init-
		/// Phase z.B. mit dem 'OnClick' mitgegeben werden (siehe hierzu
		/// 'protected override void OnInit(EventArgs e)'.</param>
		public void RaisePostBackEvent(string eventArgument)
		{
			// Ist das Event vom Button gekommen?
			if (eventArgument == "btn")
			{
				// Click ereignis dieses CustomControls wird ausgelöst.
				OnClick(new EventArgs());
			}

			// Ist das Event von der TextBox gekommen?
			if (eventArgument == "txt")
			{
				// TextChanged ereignis dieses CustomControls wird ausgelöst.
				OnTextChanged(null);
			}
		}

		/// <summary>
		/// Diese Methode wird aufgerufen, wenn die Anzeige-Seite bemerkt, dass Daten per Post an das CustomControl
		/// gesendet wurde. Zuvor muss die Anzeige-Seite darüber informiert werden, dass Post-Daten weitergereicht
		/// werden soll. Das geschieht mit 'this.Page.RegisterRequiresPostBack(this);'.
		/// Weiterhin entscheidet diese Methode dann darüber, ob sich aufgrund der gesendeten Daten ein Ereignis
		/// zu feuern wäre. Das bewirkt dann beim Rücksenden von 'true', dass im Folgenden die Anzeige-Seite die
		/// Methode 'RaisePostDataChangedEvent()' aufruft, beim Senden von false wird das unterlassen.
		/// </summary>
		/// <param name="postDataKey">Beinhaltet einen String-Key, der das Control näher definiert, für den
		/// Post-Daten vorliegen.</param>
		/// <param name="postCollection">Ein Container der die Post-Daten beinhaltet.</param>
		/// <returns></returns>
		public bool LoadPostData(string postDataKey, NameValueCollection postCollection)
		{
			// Entscheide, ob sich ein neuer Wert für die Textbox ergeben hat seit dem letzten Post-Back
			if (txtField.Value != Convert.ToString(postCollection["txtField"]))
			{
				// Es haben sich änderungen ergeben. Trage diese Änderungen in die Textbox ein, denn ich
				// hätte auch die Möglichkeit diese zu verwerfen.
				txtField.Value = Convert.ToString(postCollection["txtField"]);
				this.Page.Session.Add("txtField", txtField.Value);

				// Weitergehendes Event soll gefeuert werden (TextChanged), deshalb true
				return true;
			}

			// Keine Änderungen zu letzten Daten vorhanden, unterlasse weitergehende Event-Feuerung.
			return false;
		}

		/// <summary>
		/// Wird aufgerufen, wenn 'LoadPostData' true zurückliefert. Hier kann dann entschieden werden, bestimmte
		/// Events zu feuern mit der On...Event-Methode. Z.B. wenn überprüft wurde, dass eine Text-Box ihren Wert
		/// verändert hatte, dann kann ich, wie hier definiert das TextChanged-Event feuern lassen.
		/// </summary>
		public void RaisePostDataChangedEvent() 
		{ 
			// Löse TextChanged Event aus
			OnTextChanged(EventArgs.Empty);
		}


		/// <summary>
		/// Original Beschriftung: Render this control to the output parameter specified.
		/// Diese Methode wird aufgerufen, sobald das Control gezeichnet werden soll. Hier muss ich explizit angeben,
		/// was an den HTML-OutputStream geschrieben wird, damit der Browser-Client es lesen kann. Hier kann ich
		/// mittels output.Write() Plain-Text schreiben (auch Plain-Text Html-Code), oder mir Standard-Controls, die in
		/// diesem CustomControl vorhanden sind mittels 'myStandardControl.RenderControl(output);'.
		/// </summary>
		/// <param name="output"> The HTML writer to write out to </param>
		protected override void Render(HtmlTextWriter output)
		{
			output.Write(Text);
			button.RenderControl(output);
			output.Write("<br><p>");
			txtField.RenderControl(output);
			output.Write("</p>");
			chkBox.RenderControl(output);
		}


	}
}


Ciao
Norman-Timo

A: “Wie ist denn das Wetter bei euch?”
B: “Caps Lock.”
A: “Hä?”
B: “Na ja, Shift ohne Ende!”

A
AlfameisterT Themenstarter:in
154 Beiträge seit 2005
vor 18 Jahren

Danke,

ich werde es später mal durchgehen. Denn ich hänge schon wieder am nächsten CustomControl 😁