Ausprobieren: Bing Maps mit Silverlight

Von Rolf Mistelbacher Autor Feed 23. February 2010 19:34
Rund um Bing Maps hat sich die letzten Wochen und Monate einiges getan, deshalb hier mal ein Sammelsurium Blog Post mit aktuellen Infos, auch weil ich in persönlichen Gesprächen immer wieder erstaunt bin wie wenig von diesem Update bekannt ist. Mario Meir-Huber wird dann Ende März noch eine Blog Post Serie nachreichen, wo er dann anhand eines Beispiels erklärt wie Bing Maps in eigene Applikationen eingesetzt werden kann. Silverlight + Bing Maps Was vielen noch nicht aufgefallen ist – Silverlight wird jetzt als Frontend für das Browsing auf Bing Maps eingesetzt, ansehen kann man sich das unter Bing Maps Explore. Neben dem besseren Handling wird gleich Photosynth in die Bing Maps Experience integriert – Für Wien bspw.ein hier ein Screenshot mit Photosynth für die Votivkirche. Die Photosynth können User auf http://photosynth.net/ übrigens selbst erstellen und zuordnen. Es gibt hier auch eine Bing Map mit allen vorhandenen Photosynth Projekten eingezeichnet. Immerhin an die 20000 Photosynth Objekte mit 1,8 Mio. Photos sind online! Neben Photosynth ist mit Streetside ein weiterer Dienst in Bing Maps hinzugekommen den noch kaum einer kennt – wohl auch deshalb weil er in Europa noch nicht gelauncht ist. Bei Streetside lassen sich per Maus einfach durch die Straßen navigieren. Ziemlich hohe Qualität – am besten am Beispiel New York ausprobieren! Und aus aktuellem Anlass: Die Bing Maps App rund um die 2010 Olympic Games bietet alle Infos rund um die Winterspiele in Vancouver. Wer übrigens auf die klassische Bing Maps Experience ohne Silverlight zurückschalten will findet rechts unten den Button “Back to Classic”. Einen kompletteren Überblick über die neuen Features, die durch den Einsatz von Silverlight möglich wurden, findest du im Community Blog zu Bing Maps. Ressourcen für Entwickler zum AJAX SDK und Silverlight SDK Viel Spass beim Ausprobieren!

Facebook Client in Silverlight 4 Beta

Von Rolf Mistelbacher Autor Feed 4. February 2010 18:44
Für Facebook gibts eine Fülle an Clients, aber so richtig glücklich wurde ich noch mit keinem. Nun gibts mit dem Silverlight 4 Beta Client einen der nahezu alle Wünsche erfüllt, der Website Besuch auf facebook.com wird damit immer seltener – vom Photo Upload & Browsing, Statusupdates managen und Messages schreiben, oder auch Videos im Flash Format ansehen – geht jetzt alles bequem via Silverlight Client. - Silverlight 4 Beta Runtime installieren (PC Version | MAC Version) - Facebook Client installieren Video-Demo

Redbull Stratos – Felix Baumgartners Mission und unser kleines “Austrian-Team”...

Von Mario Szpuszta Autor Feed 25. January 2010 14:39
Seit letzten Freitag kurz nach der Presseankündigung von Redbull und Felix Baumgartner sind wir, vor allem Robert John, Lukas Cudrigh (Microsoft Corp.), Renate Kraus (Account Management) und das lokale Account-Team und ich sehr stolz auf http://www.redbullstratos.com (full site) http://m.redbullstratos.com (mobile site incl. iPhone support) Robert hat vor etwa 6 Monaten sofort nach einem von Renate organisiertem Enterprise Briefing mit Redbull diese Konversation gemeinsam mit Lukas Cudrigh, Director for digital marketing and online media initiatives in Redmond, und Redbull Mediahouse gestartet. Damit wurde der Startschuss für nachfolgende Technologien am Stratos Online-Auftritt gelegt: Silverlight, IIS 7.0,  IIS 7.0 smooth streaming und ASP.NET incl. AJAX   Die Stratos web site ist, so hoffen wir, nur eines der vielen Projekte in einem derartigen Rahmen auf unserer Web Plattform. Es fühlte sich, obowohl ich selbst nur ein kleines Rad bei diesem Projekt mit einigen kleinen Prototypen war, wirklich großartig an, am Freitagabend in Kitzbühel bei der lokalen Ankündigung in Österreich dabei zu sein und mit Redbull zu feiern. Die tatsächliche Implementierung des gesamten Projekts erfolgt zum Glück mit Hilfe von Microsoft Corp. und wäre ohne der Agency Terralever,die auch von Redbull USA ein Partner ist, niemals möglich gewesen. So werden wir mal sehen, was noch für Projekte und innovative Dinge hier auf uns zukommen. Für uns ist es auf jeden Fall wirklich cool, Teil dieses “Scientific Trips” zu sein!       Robert & Mario

Silverlight 4 Teil 6: COM Automatisierung in Silverlight verwenden – Word aufrufen

Von Mario Meir-Huber Autor Feed 19. January 2010 14:37
Eine weitere Neuerung in Silverlight 4 ist die COM-Automatisierung. Diese läuft jedoch NUR für die Windows Plattform. Dies bedeutet auch das man die COM-Automatisierung mit Vorsicht genießen soll. Damit man die COM-Automatisierung verwenden kann muss die Referenz auf Microsoft.CSharp.dll hinzugefügt werden. Diese muss explizit im Dateisystem gesucht werden, da jene in den normalen Assemblies in Visual Studio 2010 nicht angezeigt wird. Die DLL-Datei befindet sich normalerweise in den Program Files – Microsoft SDKs – Silverlight 4. Nun erweitern wir unseren Ribbon noch ein mal um einen Button. Wichtig ist auch das die Applikation für “Out of Browser” konfiguriert ist. Wie dies funktioniert wurde bereits in Post 2 erklärt. (COM benötigt Full Trust). Den neuen Button geben wir die Bezeichnung “Open in Word”. <Button Margin="5" Content="Open in Word" Click="Button_Click_2" /> Im Handler erstellen wir das Word-Objekt. Dies geschieht mit dem “Dynamic” Keyword. Nun sind etwas VSTO (Visual Studio Tools for Office) Kenntnisse gefordert um das Beispiel zu lösen. Zu beginn erstellen wir uns das COM-Objekt mit “Word.Application”. Danach fügen wir ein neues Dokument in Word ein. Im Dokument selbst selektieren wir eine Range (Bereich in Word, welcher zum Beispiel Text enthalten kann). Danach überprüfen wir in unserer Silverlight-Applikation ob ein Text selektiert wurde. Wenn dies so ist, setzen wir diesen Text in die Word-Applikation ein und zeigen die Applikation an. private void Button_Click_2(object sender, RoutedEventArgs e) { dynamic wordApp = ComAutomationFactory.CreateObject("Word.Application"); dynamic document = wordApp.Documents.Add(); dynamic range = document.Range(); if (!string.IsNullOrEmpty(TextArea.Selection.Text)) { range.Text = TextArea.Selection.Text; } wordApp.Visible = true; } Text editieren … … und in Word einfügen Bei dieser Gelegenheit möchte ich auch auf den WPF/Silverlight Community Day hinweisen, welcher am 29. Jänner in Graz statt finden wird. Hier werden die Silverlight 4 Neuerungen nochmal beleuchtet. Mario Meir-Huber www.meirhuber.de

Silverlight 4 Teil 5: Webcam Support in Silverlight: Live Bilder in die RichTextArea einfügen

Von Mario Meir-Huber Autor Feed 14. January 2010 14:26
Ebenso wie die vorigen Posts ist auch dieses Post aufbauend. Wir sind bereits bei Teil 5 angelangt. wo wir uns den WebCam support in Silverlight 4 ansehen. In unseren “Ribbon” aus Teil 1 fügen wir einen neuen Button ein. Dieser trägt den Namen “Live Bild”.  <Button Margin="5" Content="Live Bild" Click="Button_Click_1"></Button> Nun editieren wir den Handler. Dieser funktioniert ähnlich dem im Teil 4 erklärten Vorgehen. Wir benötigen wieder einen Paragrafen, einen InlineUIContainer und ein Image. Die WebCam können wir mit der CaptureSource ansprechen. private void Button_Click_1(object sender, RoutedEventArgs e) { Paragraph para; InlineUIContainer container; Image img; CaptureSource csource = new CaptureSource(); Um die WebCam zu verwenden überprüfen wir, ob ein Zugriff auf das Gerät überhaupt erst möglich ist. Danach greifen wir auf das Gerät mit “RequestDeviceAccess” zu. Die Methode “Start” startet die Aufnahme des Gerätes. Will man ein Bild machen, so funktioniert dies mit “AsyncCaptureImage”. Hier kann man mit Hilfe von Lamdba-Expressions das Bild aufnehmen. Wenn das Bild aufgenommen wurde, kann man die Aufnahme auch beenden. if (CaptureDeviceConfiguration.AllowedDeviceAccess || CaptureDeviceConfiguration.RequestDeviceAccess()) { csource.Start(); if (csource.State == CaptureState.Stopped) csource.VideoCaptureDevice = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice(); para = new Paragraph(); container = new InlineUIContainer(); img = new Image(); para.Inlines.Add(container); TextArea.Blocks.Add(para); //beta bug!!! container.Child = img; csource.AsyncCaptureImage(n => { img.Source = n; csource.Stop(); }); } Das Bild hier zeigt mich wie ich eben das Sample erstellt habe. Live von der WebCam ;) Bei dieser Gelegenheit möchte ich auch auf den WPF/Silverlight Community Day hinweisen, welcher am 29. Jänner in Graz statt finden wird. Hier werden die Silverlight 4 Neuerungen nochmal beleuchtet. Mario Meir-Huber Web: www.meirhuber.de Twitter: www.twitter.com/mario_mh

ASP.NET MVC: Dynamic Types mit .NET 4.0

Von Andreas Aschauer Autor Feed 12. January 2010 08:00
Die generische Klasse ViewPage des ASP.NET MVC Frameworks kann, bei Verwendung mit dem .NET Framework 4.0, auch gut genutzt werden um mit dynamic Objekten zu arbeiten. 1: public ActionResult Details() 2: { 3: dynamic detailsObject = new ExpandoObject(); 4: dynamic address = new ExpandoObject(); 5:  6: address.Street = "Musterstrasse"; 7: address.StreetNumber = "11"; 8: address.PostCode = 1111; 9:  10: detailsObject.Name = "Andreas Aschauer"; 11: detailsObject.Adress = address; 12:  13: return View(detailsObject); 14: } Einfach das dynamische Objekt zusammenbauen und die View von ViewPage<dynamic> ableiten, schon kann man mit den Eigenschaften arbeiten. 1: <%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<dynamic>" %> 2:  3: <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> 4: Details 5: </asp:Content> 6:  7: <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server"> 8: <h2>Details</h2> 9: 10: Name: <%= Model.Name %> 11: Adresse: <%= Model.Adress.Street %> 12: </asp:Content> Bei Verwendung der neuen Betaversion von Resharper 5.0bekommt man für die Properties der dynamischen Typen sogar IntelliSense Unterützung. Die ist zwar noch nicht ganz perfekt, aber schon mal ganz praktisch.

Silverlight 4 Teil 4: DropTarget mit Silverlight: Bilder in die RichTextArea einfügen

Von Mario Meir-Huber Autor Feed 11. January 2010 14:00
Eine weitere Neuerung ist DropTarget für Silverlight 4. Dies erlaubt es, Dateien vom lokalem System einfach per Drag&Drop in die Silverlight-Applikation einzufügen. Dieses Post setzt auf die vorherigen Postings zur RichTextArea auf. Damit Silverlight Drop unterstützt, muss ein Element ausgewählt werden welches dies verwenden soll. In unserem Fall ist dies die RichTextArea. Hierfür muss ein EventHandler für das “Drop”-Event eingefügt werden. Ferner muss auch “AllowDrop” auf “True” gesetzt werden.  <RichTextArea Name="TextArea" Grid.Row="1" MouseRightButtonDown="TextArea_MouseRightButtonDown" MouseRightButtonUp="TextArea_MouseRightButtonUp" Drop="TextArea_Drop" AllowDrop="True"> </RichTextArea> Unser Beispiel soll jedoch nur Bilder unterstützten. Hierfür “basteln” wir uns eine einfache Funktion, welche “IsImage” lautet und eine Datei darauf überprüft ob es sich tatsächlich um ein Bild handelt. private bool IsImage(FileInfo file) { string ext = file.Extension.ToLower(); string[] extensions = { ".bmp", ".jpg", ".jpeg", ".gif", ".png" }; return extensions.Contains(ext); } Nun können wir uns auch schon an den EventHandler machen. Dieser hat das “Drop”-Event. Neue Bilder sollen als neuer Paragraph in unsere RichTextArea eingefügt werden. Will man neue Elemente in die RichTextArea einfügen so muss man diese in einen InlineUIContainer einfügen. Dieser erlaubt alle UI-Elemente in einer RichTextArea (so zum Beispiel auch Buttons, ComboBoxen, WebBrowser, …) In den DragEventArgs befinden sich nun unsere Dateien. Diese können über das IDataObject angesprochen werden. Mit der Funktion “GetData” auf das IDataObject können wir die Dateien abfragen. Diese sind vom Typ “FileInfo[]”. private void TextArea_Drop(object sender, DragEventArgs e) { if (e.Data == null) return; Paragraph para; InlineUIContainer container; Image img; BitmapImage source; IDataObject obj = e.Data as IDataObject; if(obj != null) { FileInfo[] files = obj.GetData(System.Windows.DataFormats.FileDrop) as FileInfo[]; Nun ist es auch schon möglich, über sämtliche Dateien zu iterieren. Wenn es sich nun um ein Bild handelt wird der Stream geöffnet und in einen neuen Paragrafen eingefügt. Wichtig ist hierbei die Reihenfolge, wie eingefügt wird: BitmapImage erstellen Source für das BitmapImage setzen Paragraph, InlineUIContainer und Image erstellen Image den Source (Bild, welches in 1 und 2 erstellt wurde) hinzufügen InlineUIContainer dem Paragrafen hinzufügen Paragrafen der RichTextArea hinzufügen Bild dem InlineUIContainer hinzufügen Wichtig ist hier, das der Paragraf mit dem InlineUIContainer zuerst der RichTextArea hinzu gefügt wird. ERST DANACH DÜRFEN ELEMENT IN DEN INLINEUICONTAINER eingefügt werden. Wenn man dies nicht so macht, gibt es ne tolle Exception ;) Dies ist übrigens bei allen Elementen so, welche den InlineUIContainer eingefügt werden. Vermutlich ist dies derzeit noch ein Beta-Bug. foreach (FileInfo file in files) { if (IsImage(file)) { using(FileStream fs = file.OpenRead()) { source = new BitmapImage(); source.SetSource(fs); para = new Paragraph(); container = new InlineUIContainer(); img = new Image(); img.Source = source; para.Inlines.Add(container); TextArea.Blocks.Add(para); //beta bug!!! container.Child = img; } } } Das Bild unten erinnert mich an vergangenem Sommer … baden im angenehmen Pool zuhause … macht wirklich Sehnsucht bei diesen Temperaturen ;) Bei dieser Gelegenheit möchte ich auch auf den WPF/Silverlight Community Day hinweisen, welcher am 29. Jänner in Graz statt finden wird. Hier werden die Silverlight 4 Neuerungen nochmal beleuchtet. Mario Meir-Huber www.meirhuber.de

Design Patterns: Teil 3 - Testbarkeit

Von Andreas Aschauer Autor Feed 11. January 2010 11:51
Ziel dieser Blogreihe soll es nicht sein Pattern A bis Z vorzustellen (dafür gibt es genügend Bücher) sondern praktische Tutorials zu liefern, wie man Design Patterns und Entwicklungsmethodiken einsetzen kann um sich das Entwicklerleben zu erleichtern und die Qualität des Codes zu verbessern. In den vorangegangen Artikeln der Design Patterns Reihe haben wir schrittweise eine modulare und lose gekoppelte Architektur entwickelt. Am Beispiel des LogWriters war schön zu erkennen, wie einfach und schnell man Modularisierung und lose Kopplung auch in scheinbar kleinen Anwendungen (die ja meist dann zu unternehmenskritischer Software heranwachsen) erreichen kann. Jetzt gehen wir einen Schritt weiter und überlegen wozu man das ganze verwenden kann. Eine gute Architektur sollte im Entwicklungsprozess auch so gut als möglich “ausgenutzt” werden, denn die Architektur allein schafft noch keinen hochqualitativen Entwicklungsprozess. Der erste Schritt dazu sind Entwicklertests! Damit ist nicht Debugging gemeint sondern eine Testgetriebene-Entwicklung, die die Brücke zwischen funktionierendem Code und Code, der funktioniert UND der Spezifikation entspricht, schlägt. Test-Driven-Development (TDD), das MVC Framework für ASP.NET und die hier vorgestellten Tools werden noch genauer in Folgeartikeln behandelt, vorerst wollen wir anhand eines kurzen Beispiels mittels ASP.NET MVC ansehen, wie leicht man Unit-Tests in einer gut strukturierten Anwendung unterbringen kann. Bis dahin sei auf die Links unten verwiesen. Erstellt man in Visual Studio ein neues MVC Projekt aus der Vorlage “ASP.NET MVC 2 Web Application”, welche via Download des ASP.NET MVC Frameworks mitgeliefert wird, wird man anfangs sofort gefragt, ob man seiner neuen Solution gleich Unit Tests hinzufügen möchte – wollen wir natürlich! Im Anhang ist der Source Code einer Minianwendung zu finden, die nichts anderes tut als eine Eingabemaske zur Verfügung zu stellen um einen Kunden neu anzulegen. Was wollen wir erreichen? Wir wollen nun testen ob beim Anlegen eines Kundendatensatzes die Muss-Felder geprüft werden und entsprechende Fehlermeldungen erscheinen. Was wir nicht wollen, ist das bei jedem Testdurchlauf Daten in die Datenbank geschrieben werden – 1. dauert das lange wenn viele Tests laufen und 2. müsste bei komplexeren Szenarien jedesmal die Datenbank zurückgesetzt werden. Genau hier kommt unsere Architektur wie wir sie im letzten Artikel erarbeitet haben zum Einsatz. Dazu implementieren wir den CustomerController folgendermassen: 1: private readonly ICustomerRepository _customerRepository; 2:  3: public CustomerController(ICustomerRepository customerRepository) 4: { 5: _customerRepository = customerRepository; 6: } 7:  8: public ActionResult Create(Customer customer) 9: { 10: if(string.IsNullOrEmpty(customer.FirstName)) 11: { 12: ModelState.AddModelError("FirstName","Firstname must not be empty!"); 13: } 14: _customerRepository.Save(customer); 15: return View(); 16: } Wichtig ist hierbei nur die Tatsache, dass die Abhängigkeit des Controllers vom CustomeRepository, dass das eigentlich Speichern übernimmt injeziiert wird. Das ermöglicht uns dass wir ein “gefaktes” CustomerRepository implementieren, also eine Klasse “CustomerRepositoryMock” die einfach ICustomerRepository implementiert und die Methode Save() so defniert wie wir sie zu Testzwecken wollen. Nämlich entweder komplett ohne Funktion oder es könnte auch eine In-Memory Datenbank wie SQLite verwendet werden. Die Implementierung ist im anghängten Sourcecode ersichtlich um den Artikel kurz zu halten. Im Prinzip folgen ICustomerRepository, CustomerRepository und CustomerRepositoryMock dem gleichen Prinzip wie die LogWriter im vorigen Artikel. Das Schöne ist nun, dass die Methode Create() des CustomerControllers einfach getestet werden kann und GANZ WICHTIG (!!) sie muss NICHT geändert werden um produktiv zu funktionieren! Es muss nur die injeziierte Instanz von ICustomerRepository zB via Windsor Container umgestellt werden -> siehe Design Patterns Teil 2 Der Test sieht dann so aus: 1: [TestMethod] 2: public void ValidationMessagesShouldAppearOnCreate() 3: { 4: var custController = new CustomerController( 5: new CustomerRepositoryMock()); 6:  7: var customer = new Customer() 8: {FirstName = ""}; 9:  10: custController.Create(customer); 11:  12: Assert.AreEqual(1, custController.ModelState.Count); 13: Assert.AreEqual("Firstname must not be empty!", custController.ModelState["FirstName"].Errors[0].ErrorMessage); 14:  15: } Die 2 Assert() Anweisungen prüfen, ob im ModelState der Key “FirstName” vorhanden ist und ob der Eintrag die richtige Fehlermeldung enthält. Hier ist auch schön zu sehen, wie einfach die UI im ASP.NET MVC Framework getestet werden kann. Eine Einführung ins MVC Framework und noch viel mehr zu TDD und Unit Testing folgen in den nächsten Artikeln! Links/Downloads: Beispiel Source Code ASP.NET MVC Framework Einführung in TDD

ASP.NET Tutorial – Eigene Server Controls bauen – Teil 2

Von Max Knor Autor Feed 7. January 2010 09:00
Im ersten Teil dieses Mini-Tutorialshabe ich gezeigt, wie Sie ein simples Button ASP.NET Webcontrol bauen können. Dieses Control leitet von WebControl ab, rendert eigene HTML-Tags und verwendet IPostBackEventHandler, um auf das Javascript onClick Event des Buttons zu reagieren. Im zweiten Teil dieses Mini-Tutorials entwickeln wir wie versprochen ein eigenes ASP.NET Textbox Control, das ein Subset der bestehenden TextBox Klasse implementiert und die funktionsweise von ASP.NET zeigen soll. Was ist nun der wesentliche Unterschied eines Buttons zu einer TextBox, könnten sich nun ungeduldige Leser fragen – ist das nicht das Gleiche in Grün? Der Unterschied zwischen TextBox und Button liegt in der Art des Events und seiner Auslösung: Beim Button reicht es dem Server mitzuteilen, dass der Button gedrückt wurde. Bei der TextBox ändert sich der Textinhalt, also ein Event, das gleichzeitig auch den neuen Inhalt als Übergabewert braucht. Rendern der HTML Tags Beginnen wir wieder mit einer neuen Klasse, die wiederum HTML-Tags in der Render Methode in die Seite schreibt. public class CustomTextbox : WebControl, IPostBackDataHandler { protected override void Render(HtmlTextWriter writer) { this.AddAttributesToRender(writer); writer.AddAttribute(HtmlTextWriterAttribute.Name, this.UniqueID); writer.AddAttribute(HtmlTextWriterAttribute.Type, "text"); ; writer.AddAttribute(HtmlTextWriterAttribute.Value, this.Text); // Something is missing here -- Point A writer.RenderBeginTag(HtmlTextWriterTag.Input); writer.RenderEndTag(); } public string Text { get { return (string)this.ViewState["Text"]; } set { this.ViewState["Text"] = value; } } static readonly object EventTextChanged = new object(); public event EventHandler TextChanged { add{base.Events.AddHandler(EventTextChanged, value);} remove{base.Events.RemoveHandler(EventTextChanged, value);} } } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } Binden Sie das CustomTextbox Control (wie in Teil 1 des Mini-Tutorials beschrieben) neben einen Button in ihre Seite ein. Implementieren Sie einen onClick Eventhandler für den Button, um dort mittels eines Breakpoints im WatchWindow den Wert von CustomTextbox.Text zu überprüfen. Eventverarbeitung Auch wenn Sie den Text manuell ändern, wird die Text Eigenschaft immer gleich (leer) bleiben. Das liegt daran, dass die Formulardaten vom Postback erst am Server ausgewertet werden müssen. Dies wird über das Interface IPostBackDataHandlergemacht. Dieses definiert zwei Methoden: public bool LoadPostData(string postDataKey, NameValueCollection postCollection) { if (this.Text != postCollection[postDataKey]) { this.Text = postCollection[postDataKey]; return true; } else return false; } public void RaisePostDataChangedEvent() { EventHandler handler = (EventHandler)base.Events[EventTextChanged]; if (handler != null) handler(this, EventArgs.Empty); } In LoadPostData haben wir über die postCollection Zugriff auf alle Formularwerte, postDataKey ist der Key des jeweilige Controls. In der Implementierung vergleichen wir, ob der neu gepostete Formularwert der TextBox anders ist, als der bisherige. Ist dies der Fall (der Rückgabewert true), so wird automatisch RaisePostDataChangedEvent aufgerufen. In dieser Methode können wir implementieren, wie ein Event gefeuert werden soll, falls sich Daten verändert haben. Die Eventverarbeitung läuft nun wie folgt ab: Textbox Inhalt wird geändert Click auf den Button löst Postback zum Server aus Da die Textbox IPostBackDataHandler implementiert, wird LoadPostData aufgerufen Gepostete Daten sind anders als der Letztstand aus dem ViewState Text Inhalt wird am Server (und im ViewState) verändert TextChanged Event wird am Server gefeuert. Button – Click Event wird am Server gefeuert. Eine mögliche Schwäche liegt im Postback: Erst wenn ein anderes Control (z.B. Button) einen Formular Postback zum Server auslöst, werden auch die neuen Textboxwerte verarbeitet. Wichtig: Wenn TextChanged & Button.Click Events beim gleichen Postback gefeuert werden (wie hier), passiert dies immer zuerst für alle xxxChanged Events, dann für alle Submit/Click-Events. (Man könnte auch sagen, IPostBackDataHandler wird vor IPostBackEventHandler aufgerufen). Auto-Postbacks Die Lösung für das oben beschrieben Problem heißt Auto-Postback. Sobald sich der Inhalt des HTML-Input Controls ändert, soll sofort ein Postback zum Server gemacht werden, ohne auf spätere Button-Clicks oder andere Aktivitäten zu warten. Um Auto-Postback zu implementieren, benötigen wir eine neue Eigenschaft: public bool AutoPostBack { get; set; } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } Wenn AutoPostBack am Control aktiviert ist, können wir in der Render Methode (an Point A) im Falle des onChange Javascript Events einen manuellen Postback rendern: if (this.AutoPostBack) { writer.AddAttribute(HtmlTextWriterAttribute.Onchange, this.Page.ClientScript.GetPostBackEventReference(this, "")); } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } Das würde ein clientseitiges HTML-Input Tag bewirken, das so aussieht: <input type="text" value="Meine Textbox" onchange="__doPostBack('CustomTextbox1','')" /> .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } Download: Beispielcode zum Mini-Tutorial knom

ASP.NET Tutorial – Eigene Server Controls bauen – Teil 1

Von Max Knor Autor Feed 5. January 2010 09:00
Wie ich in Teil 1& Teil 2der ASP.NET Webcastserie bereits ausführlich erklärt habe, verwendet ASP.NET das Konzept von Server Controls als eine Abstraktion über konkrete HTML Tags. In diesem Posting zeige ich, wie Sie eigene Server Controls bauen können, was nicht nur für Control-Developer interessant ist, sondern auch einen Einblick in die Funktionsweise von ASP.NET gibt. Als Beispiel bauen wir zwei ASP.NET Controls – Textbox und Button – in einer vereinfachten Version komplett neu. Beginnen wir mit dem Button. Alle ASP.NET WebControls leiten sich von System.Web.UI.WebControls.WebControlab. Nochmals zur Erinnerung: WebControls haben einheitliche Eigenschaftsnamen, die aber nicht 1:1 den Original-HTML Tags entsprechen (im Gegensatz zu den HtmlControls, die das jeweilige HTML Tag genau wrappen). Für den Button wird eine neue Klasse benötigt, die von WebControl ableitet und eine Texteigenschaft, sowie ein Event besitzt: 1: public class CustomButton : WebControl { 2: public string Text 3: { 4: get { return (string)this.ViewState["Text"]; } 5: set { this.ViewState["Text"] = value; } 6: } 7:   8: static readonly object EventClick = new object(); 9: public event EventHandler Click 10: { 11: add { base.Events.AddHandler(EventClick, value); } 12: remove { base.Events.RemoveHandler(EventClick, value); } 13: } 14: } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } Damit der Button sich die Texteigenschaft auch über HTML-Form-Posts hinweg merken kann, wird der Wert im ViewState gespeichert. Der ViewState wird in der HTML Seite als Hidden-Field gerendert, das bei einem Postback als State der Seite wieder zum Server mitgeschickt wird: <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwUJMjg1MTUxMzYwD2QWAgozjUghfwDH9ZQHmo=" /> .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } Die Events werden in einer zentralen Events-Liste gespeichert. Rendern der HTML Tags Um den Button zu rendern wird die Render Methode innerhalb des Button-WebControls überschrieben. Diese Methode bietet ein HtmlTextWriter Objekt an, mit dessen Hilfe in den Ausgabestream geschrieben werden kann. protected override void Render(HtmlTextWriter writer) { // Something is missing here -- Point A writer.AddAttribute(HtmlTextWriterAttribute.Name, this.UniqueID); writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID); writer.AddAttribute(HtmlTextWriterAttribute.Type, "button"); ; writer.AddAttribute(HtmlTextWriterAttribute.Value, this.Text); // Something is missing here -- Point B writer.RenderBeginTag(HtmlTextWriterTag.Input); writer.RenderEndTag(); } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } Durch die Methode AddAttribute werden Attribute für das HTML Tag festgelegt. RenderBeginTag / RenderEndTag rendert dann letztlich das Input Tag mit den Attributen. Den Button ausprobieren Um das Control im selben Projekt auszuprobieren, muss in der Web.config eine Referenz auf den Namespace hinzugefügt werden: <pages> <controls> <add tagPrefix="cc" namespace="Knom.Web.UI.CustomControls" assembly="Knom.Web.UI.CustomControls"/> // ... </controls> </pages> .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } Nun kann der Button in die ASP.NET Seite eingebunden werden: <cc:CustomButton ID="Button1" runat="server" Text="Save" /> Alternativ kann der Button (meist erst nach einem Rebuild) auch direkt aus der Toolbox in die Seite gezogen werden:   Wenn Sie die Seite nun starten, sehen Sie, wie der Button in HTML gerendert wird: <input type="button" value="Mein Text" Name="Button1" ID="Button1" /> .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } Der Button sieht bereits richtig aus, allerdings funktioniert er noch nicht… Eventverarbeitung Damit ASP.NET am Server ein Event feuert, muss die Webseite das HTML Formular, in dem sich alle Tags befinden zum Server versenden. Dies passiert über eine Javascript Hilfesmethode, die ASP.NET in jede Seite einbaut: function __doPostBack(eventTarget, eventArgument) { if (!theForm.onsubmit || (theForm.onsubmit() != false)) { theForm.__EVENTTARGET.value = eventTarget; theForm.__EVENTARGUMENT.value = eventArgument; theForm.submit(); } } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } __doPostBack setzt bevor das Formular abgeschickt wird noch die Hidden-Fields EVENTTARGET und EVENTARGUMENT. Diese beiden werden vom Server ausgewertet, um festzustellen, welches Control welches Event ausgelöst hat. Der erste Schritt für Events ist es, das gerenderte HTML um ein onClick Javascript Event zu erweitern, das __doPostBack aufruft: <input type="button" ... onClick="__doPostBack('Button1','')" /> .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } Dies geschieht wiederum in der Render Methode. Am Point B fügen Sie folgende Zeile ein: writer.AddAttribute(HtmlTextWriterAttribute.Onclick, this.Page.ClientScript.GetPostBackEventReference(this, "")); .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } GetPostBackEventReference ist eine Hilfsmethode, die den richtigen Aufruf für __doPostBack einfügt. Damit der Button das Event beim PostBack am Server auch empfangen kann, muss auf der CustomButton Klasse noch das IPostBackEventHandler Interface implementiert werden: public class CustomButton : WebControl, IPostBackEventHandler { // ... public void RaisePostBackEvent(string eventArgument) { EventHandler handler = (EventHandler)Events[EventClick]; if (handler != null) handler(this, EventArgs.Empty); } } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } Das Interface definiert die RaisePostBackEvent Methode, die wir nutzen um die Eventhandler aus der Eventliste zu feuern. Die Eventverarbeitung ist nun fertig implementiert und läuft nochmals zusammengefasst so ab: HTML-Input-Button wird gedrückt __doPostBack(‘Button1’,’’) löst einen Formular Postback zum Server aus Aufgrund des EVENTTARGETs (‘Button1’) wird der Button gesucht Da der Button IPostBackEventHandlerimplementiert, wird die Methode RaisePostBackEvent aufgerufen. Alle Eventhandler für das Click Event werden aufgerufen. Nun kann der CustomButton in der ASP.NET Seite durch einen Eventhandler erweitert werden, um das Click Event zu testen. Auch eine Farbe darf nicht fehlen: <cc:CustomButton ID="Button1" runat="server" Text="Save" onClick="Button1_Click" BackColor="Red"/> .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } ASP.NET Styles mitrendern Alle WebControls haben gewisse Standardeigenschaften wie BackColor, BorderColor, BorderStyle, Font, etc. Diese Eigenschaften werden von unserem CustomButton derzeit noch ignoriert. Damit sie als CSS-Eigenschaften gerendert werden, muss folgende Zeile in der Render Methode (an Point A) eingefügt werden: this.AddAttributesToRender(writer); .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } Wenn Sie jetzt die Seite neustarten, wird der Button rot gerendert. Wie man eine eigene TextBox bauen kann lernen Sie im ASP.NET Tutorial – Eigene Server Controls bauen – Teil 2! Download: Beispielcode zum Mini-Tutorial knom

Silverlight 4 Teil 3: Der Rechtsklick nun auch etwas anders

Von Mario Meir-Huber Autor Feed 4. January 2010 22:31
Dieses Beispiel erklärt den neuen Rechtsklick in Silverlight 4. Dieser kann nun das vorher omnipräsente Rechtsklick-Menü ersetzen. Das Beispiel dient als Erweiterung zu Teil 1 – die RichTextArea. Damit unser Rechtsklick auch Sinn macht, müssen wir ein Menü anzeigen. Hierfür erstellen wir ein Popup. Dieses enthält ein StackPanel mit den drei typischen Operationen “Einfügen, kopieren und ausschneiden”. <Popup Name="popUp" MouseLeftButtonUp="popUp_MouseLeftButtonUp"> <StackPanel> <Button Content="Paste" Click="ClipOperations" /> <Button Content="Copy" Click="ClipOperations"/> <Button Content="Cut" Click="ClipOperations"/> </StackPanel> </Popup> Unser Rechtsklick soll nun mit der RichTextArea verknüpft werden. Damit der Rechtsklick nicht das bereits vorhandene Silverlight 4 Menü anzeigt, muss im “RightButtonDown”-Event des gewünschten Rechtsklick-Objektes “e.Handled” auf “true” gesetzt werden. private void TextArea_MouseRightButtonDown(object sender, MouseButtonEventArgs e) { e.Handled = true; } Unser Menü wird nun im “MouseRightButtonUp” angezeigt. Die Position für unser Popup setzen wir über den HorizontalOffset und den VerticalOffset. Die Position bekommen wir mit e.GetPosition(this). private void TextArea_MouseRightButtonUp(object sender, MouseButtonEventArgs e) { popUp.HorizontalOffset = e.GetPosition(this).X; popUp.VerticalOffset = e.GetPosition(this).Y; popUp.IsOpen = true; }   Damit können wir bereits ein Menü anzeigen. Nun fehlen nur noch die Operationen. Hierfür wird der Text (Content) des Buttons verwendet. Will man Text einfügen, so stellt die Klasse “Clipboard” die statische Methode “ContainsText()” zur Verfügung. Diese liefert uns einen boolschen Wert, ob Text in der Zwischenablage vorhanden ist. Damit keine Exception auftritt, muss die RichTextArea auch noch auf eine vorhandene Selection überprüft werden. Die “SetText” und “GetText”-Methoden der RichTextArea erlauben uns nun, Text einzufügen beziehungsweise zu löschen. private void ClipOperations(object sender, RoutedEventArgs e) { string operation = ((Button)sender).Content.ToString(); switch (operation) { case "Cut": if(Clipboard.ContainsText() && !string.IsNullOrEmpty(TextArea.Selection.Text)) { Clipboard.SetText(TextArea.Selection.Text); TextArea.Selection.Text = string.Empty; } break; case "Paste": if (Clipboard.ContainsText()) { TextArea.Selection.Text = Clipboard.GetText(); } break; case "Copy": if (!string.IsNullOrEmpty(TextArea.Selection.Text)) { Clipboard.SetText(TextArea.Selection.Text); } break; } popUp.IsOpen = false; } Dies wäre nun der Rechtsklick und die Clipboard-API. In den nächsten Posts geht es mit Bildern und DropTarget für die RichTextArea weiter! Hier geht es zum Überblick zu Silverlight 4 Bei dieser Gelegenheit möchte ich auch auf den WPF/Silverlight Community Day hinweisen, welcher am 29. Jänner in Graz statt finden wird. Hier werden die Silverlight 4 Neuerungen nochmal beleuchtet. Mario Meir-Huber www.meirhuber.de

Codefest.at Wochenrückblick: 28.12.2009 bis 02.01.2010

Von Mario Meir-Huber Autor Feed 2. January 2010 23:41
Der Codefest Wochenrückblick informiert über die Geschehnisse rund um .NET der letzten Woche. Damit möchten wir unseren Lesern einen kleinen Wegweiser bieten, der die Fülle an Information, die wöchentlich auf MSDN und vielen anderen Stellen im Web veröffentlicht wird, vorsortiert präsentiert. Wenn Du etwas interessantes vermisst, bitte einfach in den Comments ergänzen! User Experience und Design MEF und Silverlight In diesem Screencast wird das Managed Extensibility Framework gemeinsam mit Silverlight vorgestellt. Wenn Erweiterbarkeit ein wichtiger Punkt ist, ansehen! Silverlight und Support Das Silverlight Team von Microsoft gibt Informationen über den Support in Silverlight. Dies ist für Unternehmen, welche Silverlight verwenden, oft sehr wichtig. Quo Vadis, Silverlight? Computerworld.ch hat einen sehr spannenden Artikel über die “Marschrichtung” von Silverlight 4 erstellt. Hierbei wird auch festgestellt das Silverlight 4 vor allem für Geschäftsanwendungen interessant ist. Lese- und Linktipps Scott Hanselman’s 2009 Top-Beiträge Scott Hanselman hat eine Liste seiner Toplinks und Topbeiträge zusammen gestellt. Hier sollte sich für jeden noch einiges interessantes an Lesestoff ergeben. Mario Meir-Huber www.meirhuber.de

Silverlight 4 Teil 2: Das HTML Steuerelement

Von Mario Meir-Huber Autor Feed 2. January 2010 13:16
Auf der PDC letzten Jahres (ja bereits letztes Jahr) wurde Silverlight 4 durch Scott Guthrie angekündigt. Neben der RichTextArea war eine der interessantesten Demos die HTML-Unterstützung. Besonders interessant ist, das hierbei alles unterstützt wird, was auch der Internet Explorer unter Windows kann. Für Mac-Systeme ist dies der Safari. Dies bedeutet nun, das auch Plug-ins wie Flash unterstützt werden. Das WebBrowser-Steuerelement ist sehr einfach zu bedienen. Man fügt einfach den Tag “WebBrowser” hinzu. Für unser Demo (welche dieses mal nichts mit der RichTextArea zu tun haben wird) benötigen wir noch zwei RowDefinitions. In die erste Reihe kommt ein StackPanel mit einem Text und einem Button rein. Die zweite Reihe bekommt nun den WebBrowser als Inhalt. <Grid x:Name="LayoutRoot" Background="White"> <Grid.RowDefinitions> <RowDefinition Height="35" /> <RowDefinition /> </Grid.RowDefinitions> <StackPanel Orientation="Horizontal"> <TextBox Margin="5" Width="300" Name="txtUrl" /> <Button Content="Go!" Margin="5" Click="Button_Click" /> </StackPanel> <WebBrowser Grid.Row="1" Name="browser"> </WebBrowser> </Grid> Der oben erstellte Button erlaubt uns nun, zu verschiedenen Seiten zu navigieren. Dies funktioniert mit einer URI, wobei der Kind auf “Absolute” gesetzt werden muss. private void Button_Click(object sender, RoutedEventArgs e) { browser.Navigate(new Uri((txtUrl.Text), UriKind.Absolute)); }   Will man nun dieses Beispiel ausführen, so sieht man sofort das da etwas nicht so läuft wie man es erwarten würde: das WebBrowser Steuerelement kann nicht angezeigt werden. Damit der WebBrowser funktioniert, muss dieser “Out of Browser” laufen. Der Grund hierfür ist sehr einfach: es kann sehr einfach eine Rekursion entstehen. Würde es auch im Browser laufen, so könnte man die Seite mit dem Silverlight-Plug-in ansurfen, welches die Seite mit dem Silverlight-Plug-in enthält, welches die Seite mit dem Silverlight-Plug-in enthält, welches die Seite mit dem Silverlight-Plug-in enthält, welches die Seite mit dem Silverlight-Plug-in enthält, … Out of Browser in Silverlight 4 kann sehr einfach über die Projekteinstellungen im Projekt erstellt werden. Hierfür muss “Enable running application out of the Browser” aktiviert werden. Danach muss man auch noch die Out-of-Browser-Einstellungen konfigurieren. Hierfür wird “Show install menu” und “Require elevated trust when running outside of the browser” auch noch benötigt. Führt man die Applikation nun Out-of-Browser aus, so wird das HTML-Element nun angezeigt. Wichtig ist auch, das vor dem “www” immer ein “http://” steht. Hier geht es zum Überblick zu Silverlight 4 Bei dieser Gelegenheit möchte ich auch auf den WPF/Silverlight Community Day hinweisen, welcher am 29. Jänner in Graz statt finden wird. Hier werden die Silverlight 4 Neuerungen nochmal beleuchtet. Mario Meir-Huber www.meirhuber.de

Silverlight 4 Teil 1: Die RichTextArea erklärt

Von Mario Meir-Huber Autor Feed 30. December 2009 13:02
Eine der interessantesten Neuerungen in Silverlight 4 ist die RichTextArea. Mit dessen Hilfe kann man schön formatierten Text in Silverlight 4 erstellen. Wie dieser funktioniert wird in diesem Beitrag erläutert. Die RichTextArea ist sehr funktional, weshalb diese auch in den weiteren Beispielen verwendet wird. Also: das Projekt sehr gut aufheben, es wird in den nächsten Wochen wieder benötigt :). Bevor wir beginnen müssen wir uns für ein Layout entscheiden. Wir werden eine Art Ribbon basteln – jedoch auf sehr sehr einfacher Weise. Hierfür brauchen wir eine Reihe mit der Höhe von 45 Pixeln. Im unteren Bereich wollen wir auch noch 30 Pixel frei halten. Eine Reihe von flexibler Größe wird in die Mitte gegeben. <Grid x:Name="LayoutRoot" Background="White"> <Grid.RowDefinitions> <RowDefinition Height="45"></RowDefinition> <RowDefinition /> <RowDefinition Height="30"></RowDefinition> </Grid.RowDefinitions> Danach legen wir einen Verlauf für den “Ribbon” fest. Ein LinearGradientBrush erfüllt diese Anforderung voll und ganz. Der Ribbon wird in einem StackPanel mit einer Horizontalen Ausrichtung angegeben. <StackPanel Orientation="Horizontal"> <StackPanel.Background> <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> <GradientStop Color="#6668A0FF" Offset="1"/> <GradientStop Color="#7F1246A1"/> </LinearGradientBrush> </StackPanel.Background> Die RichTextArea wird im Grid in der Reihe “1” eingefügt. Wie dies aussieht ist in der vorletzten Zeile des nachfolgenden Codes ersichtlich. Für unser Word-Nachbau brauchen wir vorerst drei Buttons und eine ComboBox (erweitert wird diese in den nächsten Einträgen). Der erste Button ist für fett, der zweite für kursiv und der dritte für unterstrichen zuständig. Die ComboBox enthält einige Schritgrößen von 8-22. <Button Margin="5" FontWeight="Bold" Width="40" Content="B" Click="Button_Click" /> <Button Margin="5" FontStyle="Italic" Width="40" Content="I" Click="Button_Click" /> <Button Margin="5" Width="40" Click="Underline"> <TextBlock> <Run TextDecorations="Underline">U</Run> </TextBlock> </Button> <ComboBox Width="150" Margin="5" SelectedValue="12" SelectionChanged="ComboBox_SelectionChanged"> <ComboBoxItem Content="8" /> <ComboBoxItem Content="10" /> <ComboBoxItem Content="12" /> <ComboBoxItem Content="14" /> <ComboBoxItem Content="16" /> <ComboBoxItem Content="18" /> <ComboBoxItem Content="22" /> </ComboBox> </StackPanel> <RichTextArea Name="TextArea" Grid.Row="1"></RichTextArea> </Grid> Im nächsten Schritt wollen wir den Eventhandler für die ersten zwei Buttons erstellen. Dies ist fett und kursiv. Wichtig ist vorweg, das eine RichTextArea verschiedene Selektionen erlaubt. Diese sind über die “Selection” Property aufrufbar. Hier kann man mit “SetPropertyValue” die Eigenschaften setzen. Fett schreiben kann man mit der “FontWeightProperty”, kursiv mit der “FontStyleProperty” Enumeration. private void Button_Click(object sender, RoutedEventArgs e) { string cmd = ((Button)sender).Content.ToString(); if (!string.IsNullOrEmpty(TextArea.Selection.Text)) { switch (cmd) { case "B": TextArea.Selection.SetPropertyValue(TextElement.FontWeightProperty, FontWeights.ExtraBlack); break; case "I": TextArea.Selection.SetPropertyValue(TextElement.FontStyleProperty, FontStyles.Italic); break; default: break; } } } Ähnlich wie bei fett und kursiv verhält es sich auch bei unterstrichen. Hierfür verwenden wir das TextElement.TextDecorationsProperty mit TextDecorations.Underline. private void Underline(object sender, RoutedEventArgs e) { if (!string.IsNullOrEmpty(TextArea.Selection.Text)) { TextArea.Selection.SetPropertyValue(TextElement.TextDecorationsProperty, TextDecorations.Underline); } } Und natürlich verhält sich auch die ComboBox ähnlich. Hierfür wird die Schriftgröße geändert sobald die ComboBox-Selection sich geändert hat. private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { ComboBox c = sender as ComboBox; ComboBoxItem ci = c.SelectedValue as ComboBoxItem; if (!string.IsNullOrEmpty(TextArea.Selection.Text)) { TextArea.Selection.SetPropertyValue(TextElement.FontSizeProperty, ci.Content); } } Die RichTextArea in Silverlight 4 bietet einige interessante Möglichkeiten. Jedoch ist dies nur ein sehr allgemeiner Einführungsteil. Mehr zu der RichTextArea wird in den kommenden Beispielen enthalten sein, wo die weiteren Änderungen zu Silverlight 4 vorgestellt werden. Hier geht es zum Überblick zu Silverlight 4 Bei dieser Gelegenheit möchte ich auch auf den WPF/Silverlight Community Day hinweisen, welcher am 29. Jänner in Graz statt finden wird. Hier werden die Silverlight 4 Neuerungen nochmal beleuchtet. Mario Meir-Huber www.meirhuber.de

Entwickeln von Web-Applikationen - Das ASP.NET Tutorial Webcast-Lernpaket auf Codefest

Von Rolf Mistelbacher Autor Feed 28. December 2009 15:50
Das ASP.NET Tutorial für Einsteiger, Beginner, Nachleser... Max hat die letzten Wochen 7 Live Webcasts zu ASP.NET abgehalten – für alle die in die Programmierung von Web-Applikationen mit ASP.NET einsteigen wollen ein ideales Set an Content. Von der grundlegenden Architektur einer dynamischen Website, den Einsatz von AJAX, Datenbankzugriff, bis zum Publishing der Website am Webserver wird alles erklärt – also ideal für Einsteiger die einen ganzheitlichen Überblick erhalten wollen. Hier nun die Webcasts in einem Blog Post zusammengefasst, mit Download & Streaming Link, als auch Verweis auf die zugehörigen Unterlagen. Außerdem wurde das MSDN Briefing zu ASP.NET im Oktober aufgezeichnet, die Links dazu werden am Ende ergänzt! 7teilige Webcast Serie (für den Download rechtslick auf Download link > Ziel speichern unter, Dauer jeweils ~1h): Teil Inhalt Video Unterlagen & Demos 1 Das ASP.NET Basisframework, Überblick, Webforms Stream Download Download 2 ASP.NET Webforms, State Management Stream Download Download 3 Datenbindung und Validierung Stream Download Download 4 Durchgängiges Aussehen und Navigation Stream Download Download 5 Rechtevergabe, Membership Controls Stream Download Download 6 Websites mit ASP.NET AJAX erweitern Stream Download Download 7 Publishing von Websites und Hosting auf dem Internet Information Server 7 (IIS 7) Stream Download Download MSDN Briefing zu “Webapplikationen mit ASP.NET entwickeln” vom 23. Oktober 2009 – Dauer je ~1h Session Video Unterlagen 1. - ASP.NET Webforms Download Stream Download 2. – ASP.NET Datenzugriff, ASP.NET AJAX Download Stream Download 3. – IIS 7 Architektur, Web Platform Installer, Deployment von ASP.NET Web Apps Download Stream Download

Datenschutz & Cookies · Nutzungsbedingungen · Impressum · Markenzeichen
© 2013 Microsoft. Alle Rechte vorbehalten · BlogEngine.NET 2.7.0.0 · Diese Website wird für Microsoft von atwork gehostet.
powered by atwork