Wednesday, January 31, 2007

Paint.NET

Auch als Software Entwickler ist ein Grafikprogramm immer wieder von nutzen. Nur soll es nicht so teuer und kompliziert sein wie ein PhotoShop und doch etwas mehr Möglichkeiten bieten als ein Paint.
Definitiv das richtige Tool für den .NET Entwickler ist Paint.NET. Dies ist nicht etwa Paint in .NET programmiert sondern wirklich ein kleiner aber feiner PhotoShop.

Hier geht's zum Produkt. Übrigens, es gibt's sogar den Source Code zum downloaden ;-)

Monday, January 29, 2007

Redirecting to another page

Um von einer zur anderen Seite navigieren zu können, kennen wir heute die unterschiedlichsten Methoden. Mit ASP.NET werden hauptsächlich vier Arten eingesetzt.
- Hyperlinks
- Browser Redirect
- Server Transfer
- Cross-Page Posting

Die Vor- und Nachteile werden hier von Microsoft beschrieben.


Für alle die immer noch eine gewisse Unsicherheit spüren, hier noch ein paar Ergänzungen.

Sofern von der einen zur anderen Seite keine Daten übertragen werden müssen, sollte der Hyperlink verwendet werden. Ausnahme, wenn man die URL 'verstecken' will.

Auf das Redirect wird wenn immer möglich verzichtet, da dies einen zusätzlichen Roundtrip bedeutet.

Wenn Daten ausgetauscht werden müssen, kommen die beiden Möglichkeiten 'Server Transfer' und 'Cross-Page Posting' ins Spiel.
'Cross-Page Posting' ist seit ASP.NET 2.0 möglich und die etwas schönere Variante. Dabei ändert sich die Browserfunktionalität nicht, jedoch muss das Ziel fix verdrahtet werden.
Beim 'Server Transfer' ist ein GoBack im Browser nicht möglich, die dynamische Adressierung jedoch kein Problem.
In der Praxis merkt man aber sehr schnell, dass beide Methoden ihre Berechtiging haben und man am Besten fährt, wenn eine Kombination der beiden Möglichkeiten verwendet wird.

Datenübergabe:
Beim 'Server Transfer' werden die Daten über public Properties übergeben, die auf der aufrufenden Seite implementiert werden. Auf der Zielseite können sie über das Object Context.Handler abgefragt werden.
((PagesClassName)Context.Handler).PropertyName

Beim 'Cross-Page Posting' können die Felder mit FindControl() ausgelesen werden.
((TextBox)((PagesClassName)PreviousPage).FindControl("MyTextBox")))).Text

Diese Methode muss verwendet werden da die Controls protected sind. Aus Performance-Gründen (und OO Sicht) sollte auf diese Methode verzichtet werden. Wenn analog dem 'Server Transfer' mit public Properties gearbeitet wird, lassen sich zudem Schwierigkeiten vermeiden, die beim Einsatz von Masterpages und UserControls entstehen und mit einem zwischenschritt über den ContentPlaceholder gelöst werden müssten.
prePage = (PagesClassName)PreviousPage;
ContentPlaceHolder c = (ContentPlaceHolder)prePage .Master.FindControl("ContentPlaceHolder1");
(((TextBox)(c.FindControl("MyTextBox"))).Text



Wednesday, January 24, 2007

WPF/E for the real world

Ich war sofort begeistert von WPF/E als ich die ersten Beispiel sah. Wenn man aber erst mal einen Tag damit rumgespielt und selber die ersten Demos realister hat kommt plötzlich die Frage: War's das schon?

Im Moment ja, den wichtige Elemente für eine 'richtige' Anwendung fehlen noch. So gibt's nicht einmal eine Textbox, was die Interaktivität schwierig macht.
Das ist natürlich alles bereits angekündigt, wir müssen uns aber noch etwas in Geduld üben.

Wer schon mal einen kleinen Vorgeschmack möchte, soll sich das Beispiel von Tony anschauen. Nice!

Stay tuned, more is coming up.

Tuesday, January 23, 2007

ASP.NET AJAX 1.0 Released

Leider reichte es dazumal mit dem Release nicht auf den Projektstart vom Dezember 2006. Das wir ihn jetzt bereits bekommen haben ist aber sehr erfreulich. Dann wollen wir uns mal ans Update machen.

Den ASP.NET AJAX 1.0 Release gibt's hier. Die Online Doku ist nun auch ganz ordentlich und die Upgrade Whitepaper funktionieren.

Auch vom ASP.NET AJAX Control Toolkit gibt's am selben Ort einen neuen Release. Wie man im Blog von Scott sieht, sind ein paar schöne Controls wie der Calendar Extender dazu gekommen.

Monday, January 22, 2007

Templated Control with Designer Support

Für mein aktuelles Projekt benötigten wir eine schön formatierte Box die einen Titel hat. Statt diese auf jeder Seite x-mal mit Table Tags zu bauen und zu formatieren, wollten wir ein eigenes Control verwenden.

1. Versuch: Erstellen eines einfachen Controls abgeleitet von der Klasse Controls befriedigte unsere Bedürfnisse nur mässig, da zwischen dem Start- und Endtag nur Text verwendet werden konnte. Wir wollten jedoch ASP.NET Controls in der Box platzieren.

[DefaultProperty("Title"), ToolboxData("<{0}:SimpleBox runat=server>")]
public class SimpleBox : Control
{
private string _title;

[Bindable(true), Category("Appearance"), DefaultValue("")]
public string Title
{
get { return _title; }
set { _title = value; }
}

protected override void Render(HtmlTextWriter output)
{
string outputString = string.Empty;

// generate output (html)
outputString = "<table cellspacing="0" cellpadding="0" border="1">"
+ " <tr>"
+ " <td>" + Title + "</td>"
+ " </tr>"
+ " <tr>"
+ " <td>";

// read between the begin and end tag
if ((HasControls()) && (Controls[0] is LiteralControl))
{
outputString += ((LiteralControl)Controls[0]).Text;
}

string outputStringEnd = "</td>"
+ " </tr>"
+ "</table>";

// speak your mind
output.Write(outputString);
}
}


2. Versuch: Erstellen eines Composite Controls
Das war schon besser. Die Controls zwischen Start- und Endtag wurden erkannt und gerendert. Einziges Problem waren die Events der Childcontrols. Diese wurden nicht gefeuert. Könnte man ausprogrammieren, aber...

[DefaultProperty("Title"), ToolboxData("<{0}:ComposedBox runat=server>")]
public class ComposedBox : Control, INamingContainer
{
private string _title;

//[Bindable(true), Category("Appearance"), DefaultValue("")]
public string Title
{
get
{
return _title;
}
set
{
_title = value;
}
}

protected override void CreateChildControls()
{
string outputStringStart = "<table cellspacing="0" cellpadding="0" border="1">"
+ " <tr>"
+ " <td>" + Title + "</td>"
+ " </tr>"
+ " <tr>"
+ " <td>";

string outputStringEnd = "</td>"
+ " </tr>"
+ "</table>
";

this.Controls.AddAt(0, (new LiteralControl(outputStringStart)));
this.Controls.AddAt(this.Controls.Count - 1, (new LiteralControl(outputStringEnd)));
}
}


3. Versuch: Das Templated Control
Hier funktioniert alles auf anhieb, ohne grossen Programmieraufwand. In kurzer Zeit war unser Control erstellt und die formatierte Box stand zur Verfügung. In einer überarbeiteten Variante integrierten wir dann auch noch den fehlenden Designer Support. Great!


public class BoxTemplate : CompositeControl, INamingContainer
{
private String _message = null;
public BoxTemplate() { }
public BoxTemplate(String message)
{
_message = message;
}
public String Message
{
get { return _message; }
set { _message = value; }
}
}

[DefaultProperty("Title"),
ParseChildren(true), PersistChildren(false),
Designer("CSBS.TVCITTool.Client.Web.Controls.TemplatedBoxControlDesigner, CSBS.TVCITTool.Client.Web.Controls"),
ToolboxData("<{0}:TemplatedBox runat=server>")]
public class TemplatedBox : CompositeControl, INamingContainer
{
private string _title;
private ITemplate _messageTemplate = null;
private String _message = null;

public String Message
{
get { return _message; }
set { _message = value; }
}

[Bindable(true), Category("Appearance"), DefaultValue("")]
public string Title
{
get { return _title; }
set { _title = value; }
}

[PersistenceMode(PersistenceMode.InnerProperty), DefaultValue(null), TemplateContainer(typeof(BoxTemplate)),
TemplateInstance(TemplateInstance.Single), Browsable(false)]
public ITemplate MessageTemplate
{
get { return _messageTemplate; }
set { _messageTemplate = value; }
}

public override void DataBind()
{
EnsureChildControls();
base.DataBind();
}

protected override void CreateChildControls()
{
// If a template has been specified, use it to create children.
// Otherwise, create a single literalcontrol with message value

string outputStringStart = "
<table class="boxframe" cellspacing="'\">"
+ " <tbody><tr>"
+ " <td class="boxheader">" + Title + "</td>"
+ " </tr>"
+ " <tr>"
+ " <td>";

string outputStringEnd = "</td>"
+ " </tr>"
+ "</tbody></table>
";

if (MessageTemplate != null)
{
Controls.Clear();
BoxTemplate i = new BoxTemplate(this.Message);
MessageTemplate.InstantiateIn(i);
Controls.Add(i);
}
else
{
this.Controls.Add(new LiteralControl(this.Message));
}

this.Controls.AddAt(0, (new LiteralControl(outputStringStart)));
this.Controls.AddAt(this.Controls.Count, (new LiteralControl(outputStringEnd)));
}
}

public class TemplatedBoxControlDesigner : CompositeControlDesigner
{
private TemplatedBox _designControl;
private TemplateGroupCollection _templateGroupCollection;

public override void Initialize(System.ComponentModel.IComponent component)
{
base.Initialize(component);
_designControl = (TemplatedBox)component;
SetViewFlags(ViewFlags.DesignTimeHtmlRequiresLoadComplete, true);
SetViewFlags(ViewFlags.TemplateEditing, true);
}

public override TemplateGroupCollection TemplateGroups
{
get
{
if (_templateGroupCollection == null)
{
_templateGroupCollection = base.TemplateGroups;
TemplateGroup group;
TemplateDefinition templateDefinition;
group = new TemplateGroup("ContextRowTemplates");
templateDefinition = new TemplateDefinition(this, "MessageTemplate", _designControl, "MessageTemplate", false); //der vierte Parameter ist der Name der Property des Control
group.AddTemplateDefinition(templateDefinition);
_templateGroupCollection.Add(group);
}
return _templateGroupCollection;
}
}
}

Tuesday, January 09, 2007

Passed 70-554

I did it again... und bin nun endlich MCPD.

Hilfen und Links findet ihr in den weiteren Blogs mit dem Label Learning.

Friday, January 05, 2007

WPF/E Code Samples

Es ist noch nicht lange her das wir WPF/E erhalten haben und schon gibt's dutzende Beispiele.
Microsoft hat gleich selber ein Sample Pack erstellt das man hier downloaden kann. Weitere Informationen gibt's auf MSDN WPF/E Dev Center.
Weitere interessante Beispiele inklusive Source Code findet man im Blog von Mike Harsh hier oder hier von Richard Leggett.
Mein technisches Lieblingsbeispiel kommt von Simon, leider ohne Source Code und befindet sich hier.