dinsdag 1 juli 2008

Één ItemTemplate voor Item en AlternatingItem in ASP.NET ListView control

In het ListView control in ASP.NET 3.x is het mogelijk om een ItemTemplate én een AlternatingItemTemplate te definiëren. Veelal wordt dit gebruikt om alleen maar een andere Style of CssClass te gebruiken voor het alternating item, zodat een mooier (subjectief natuurlijk ;-)) grid wordt gecreëerd.

In plaats van twee (bijna) identieke item templates te creëren is er een eenvoudigere oplossing mogelijk:
*** ASPX ***
<ItemTemplate>
   <tr class="<%# GetListItemCssName(Container) %>">
      <td>...</td>
   <tr>
</ItemTemplate>


*** CS ***
.protected string GetListItemCssName(object container)
{
   if (container is ListViewDataItem)
   {
      if (((ListViewDataItem)container).DisplayIndex % 2 == 0)
         return "Item";
      else
         return "AlternatingItem";
   }
   return null;
}

Zoals je ziet maak ik maar één template aan, nl. het ItemTemplate. Daar waar de variatie tussen een item en alternating item toegepast moet worden (in dit geval de class attribuut van de tabel regel) roep ik een methode in mijn code-behind aan.
De methode in de code-behind bepaalt aan de hand van de DisplayIndex of het om een even of oneven regel gaat en geeft de juiste class name terug.

dinsdag 3 juni 2008

Silverlight 2 diagrammen

Momenteel ben ik veel bezig met het ontwikkelen in Silverlight 2. Toevallig kwam ik onderstaande diagrammen tegen die wel erg handig zijn voor de beginnende Silverlight ontwikkelaar.



Download het originele bestand hier



Download het originele bestand hier


Bron:
Mike Taulty's Blog

vrijdag 9 mei 2008

PSV.tv op Windows Media Center

Als voetbalfan leek het me wel leuk op de beelden van PSV.tv, Ajax.tv, Feyenoord.tv, enz. via mijn Windows Media Center te kunnen bekijken. Ik dacht: zal ik daar een apart programma voor ontwikkelen of probeer ik gebruik te maken van wat er al is? Meestal probeer ik voor de 2e optie te gaan, wat nu ook het geval was.

Wat er al is: de Media Center RSS Reader van OABsoftware voor Windows XP en Vista. Deze software is gratis te gebruiken. Alleen moet het wel geactiveerd worden, wat je kan doen door je te registreren.

Wat moet ik dan nog ontwikkelen: een programmaatje om intelligent de HTML van deze TV sites te verwerken tot RSS feeds, waar deze software goed mee om kan gaan. En dit is gelukt... helaas niet voor Feyenoord.tv want daar moet je je aanmelden om de beelden te mogen bekijken.
Iedereen die gebruik wil maken van mijn RSS feeds kan deze vinden op:
- PSV.tv
- Ajax.tv

Als je nog meer ideeën hebt voor het verwerken van dit soort webpagina's tot RSS feeds, dan laat je maar een berichtje achter op deze blog.

donderdag 8 mei 2008

Active Directory benaderen in .Net 3.5

Microsoft heeft in het .Net framework versie 3.5 de assembly System.DirectoryServices.AccountManagement toegevoegd, welke mogelijkheden biedt om redelijk eenvoudig de Active Directory (of de accountdatabase (SAM) op een lokale PC) te benaderen en te wijzigingen. In deze blog richt ik me alleen op de Active Directory (AD).

Je maakt hierbij gebruik van de PrincipalContext klasse. Hieronder een voorbeeld hoe deze klasse te instanciëren:
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "MijnDomein");
Hierbij word een 'context' gecreëerd wat de basis is voor alle acties die in de AD uitgevoerd zullen gaan worden. Er wordt daardwerkelijk een verbinding met de directory ('MijnDomein') gemaakt.

Hierna kan je eenvoudig een User of Group ophalen en eventueel wijzigen. De basis klasse die hiervoor gebruikt wordt is de Principal klasse. Hieronder een voorbeeld hoe je een User of Group ophaalt:
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, "Danny");
en
GroupPrincipal group = GroupPrincipal.FindByIdentity(ctx, "Administrators");
Met behulp van de Save methode kunnen wijzigingen op de principals doorgevoerd worden.

Een gebruiker kan ook gevalideerd worden (op bestaandheid én op correct wachtwoord). De ValidateCredentials(string userName, string password) methode van de PrincipalContext klasse kan hiervoor gebruikt worden.

Dankzij de PrincipalSearcher klasse en LINQ is het mogelijk ook relatief eenvoudig te zoeken naar Members (Users en Groups) in de Active Directory. In het voorbeeld hieronder wordt gezocht naar alle Users, welke de voornaam 'Danny' hebben:
//Creëer de context
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "MijnDomein");

//Creëer een UserPrincipal om te gebruiken voor de Query
UserPrincipal u = new UserPrincipal(ctx);
//Zet de eigenschappen om naar te zoeken
u.GivenName = "Danny";

//Creëer de PrincipalSearcher om mee te zoeken
PrincipalSearcher ps = new PrincipalSearcher(u);
// Voer de Query uit
PrincipalSearchResult results = ps.FindAll();

De FindAll methode in de PrincipalSearcher klasse geeft een PrincipalSearchResult terug, welke de mogelijkheid biedt om met behulp van LINQ queries op het resultaat uit te voeren.

Ik heb zelf wat onderzoek gedaan naar de System.DirectoryServices.AccountManagement namespace, omdat ik een lijst met gebruikers op wil vragen uit een specifieke groep in de AD. De standaard methodieken hiervoor bieden helaas alleen de mogelijkheid om de gebruikers die in de groep zelf zitten te bepalen, maar niet om recursief (groepen in groepen) te zoeken naar de gebruikers. Hieronder de code die ik heb ontwikkelt, welke dit wel mogelijk maakt:
public static List GetGroupUsers(string domainName, string groupName, bool recursive)
{
//Creëer de context
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, domainName);
//Haal de AD Group op
using (GroupPrincipal groupPrincipal = GroupPrincipal.FindByIdentity(ctx, groupName))
{
//Loop door de Members om de Users te bepalen
List result = new List();
foreach (Principal principal in groupPrincipal.Members)
{
if (principal is UserPrincipal)
result.Add(principal);
}
//Loop door de Members om de Groups recursief te benaderen
if (recursive)
{
foreach (Principal principal in groupPrincipal.Members)
{
//Controleer of de member een Group is
if (principal is GroupPrincipal)
{
//Roep deze methode aan, zodat de recursie ontstaat
foreach (Principal p in GetGroupUsers(domainName, principal.Name, recursive))
{
//geen dubbele Users in de lijst
if (!result.Contains(p))
result.Add(p);
}
}
}
}
return result;
}
}




Bronnen:
Microsoft MSDN
Boeken:
The .NET Developer's Guide to Directory Services Programming

maandag 21 april 2008

Onoplosbaar probleem in Visual Studio 2008 (?)

Onderstaand probleem is opgelost met de hulp van Microsoft. Via Microsoft Connect heb ik een feedback ingelegd en daarin is het probleem opgelost. Hiervoor dien je het volgende te doen:
  1. Open de Visual Studio 2008 Command Prompt
  2. Voer het volgende commando uit: devenv.exe /ResetSkipPkgs
  3. Het probleem zou nu opgelost moeten zijn. Hierna kan Visual Studio weer via de normale weg opgestart worden



Momenteel heb ik een probleem in Microsoft Visual Studio 2008 dat ik niet opgelost krijg. De enige oplossing die ik nu nog zie is een herinstallatie van mijn PC. Dus als iemand nog ideeën heeft dan hoor ik ze graag !!!

Het probleem wat ik heb treedt op bij het aanmaken van een nieuw C# project of het openen van een bestaand C# project in Visual Studio 2008. Hierbij geeft VS2008 de volgende foutmelding terug en opent het C# project niet:
Project 'Business.Facade' could not be opened because the Microsoft Visual C# 2008 compiler could not be created. QueryService for '{7D960B16-7AF8-11D0-8E5E-00A0C911005A}' failed.
Bij een bestaand project ziet (een deel van) de Solution Explorer in VS2008 er als volgt uit:


Nadat ik met mijn rechtermuisknop op een project klik en de optie "Reload Project" selecteer, krijg in de volgende foutmelding:


Dit probleem treedt alleen op bij C# projecten (dus bijvoorbeeld niet bij Visual Basic projecten) en de geselecteerde versie van het .Net Framework (2.0, 3.0 of 3.5) maakt in dit geval niets uit.

Ik heb een 'Repair' van de VS2008 setup uitgevoerd. Hierna heb ik VS2008 compleet verwijderd en opnieuw geïnstalleerd, maar dit gaf allemaal geen resultaat.
Als iemand nog ideeën heeft, dan graag reageren op deze blog !!

maandag 4 februari 2008

Internet Explorer javascript probleem

Ik heb nu al een aantal keer het probleem gehad dat javascript in de Microsoft Internet Explorer ineens niet meer werkte. Dit had niets met instellingen te maken, maar met iets anders.
Windows Update uitvoeren lukte niet omdat deze geheel op scripting gebaseerd is (ik kreeg alleen maar een leeg scherm te zien). Zelfs System Restore werkte niet, omdat hierbij ook gebruik van scripting gemaakt wordt.
Nog vreemder is dat de Windows Media Player niet meer opgestart kon worden.

Ik heb toen ergens op een forum de oplossing gevonden:
  1. Voer via Start\Uitvoeren het commando "regsvr32 jscript.dll" uit
  2. Voer via Start\Uitvoeren het commando "regsvr32 MSXML3.dll" uit
  3. Installeer Windows Script voor Windows XP (link: Microsoft)

Hierna was het javascript probleem opgelost en kon ik ook weer netjes een Windows Update uitvoeren.

Screen capture in C#

Screenshots of screen captures kunnen in C# gemaakt worden met behulp van een aantal API calls. Hieronder een stukje voorbeeldcode:

public const int SRCCOPY = 13369376;

[DllImport("user32.dll", EntryPoint = "GetDC")]
public static extern IntPtr GetDC(IntPtr ptr);

[DllImport("User32.dll")]
public static extern IntPtr GetDesktopWindow();

[DllImport("GDI32.dll")]
public static extern IntPtr CreateCompatibleDC(IntPtr hdc);

[DllImport("user32.dll", EntryPoint = "GetSystemMetrics")]
public static extern int GetSystemMetrics(int abc);

[DllImport("GDI32.dll")]
public static extern IntPtr CreateCompatibleBitmap(IntPtr hdc, int nWidth, int nHeight);

[DllImport("GDI32.dll")]
public static extern IntPtr SelectObject(IntPtr hdc, IntPtr hgdiobj);

[DllImport("GDI32.dll")]
public static extern bool BitBlt(IntPtr hdcDest, int nXDest, int nYDest, int nWidth, int nHeight, IntPtr hdcSrc, int nXSrc, int nYSrc, int dwRop);

[DllImport("GDI32.dll")]
public static extern bool DeleteDC(IntPtr hdc);

[DllImport("User32.dll")]
public static extern int ReleaseDC(IntPtr hWnd, IntPtr hDC);

[DllImport("GDI32.dll")]
public static extern bool DeleteObject(IntPtr hObject);


public static Bitmap CaptureScreen()
{
//In size variable we shall keep the size of the screen.
Point size = Point.Empty;

//Variable to keep the handle to bitmap.
IntPtr hBitmap;

//Here we get the handle to the desktop device context.
IntPtr hDC = GetDC(GetDesktopWindow());

//Here we make a compatible device context in memory for screen device context.
IntPtr hMemDC = CreateCompatibleDC(hDC);

//We pass SM_CXSCREEN constant to GetSystemMetrics to get the X coordinates of screen.
size.X = GetSystemMetrics(0);

//We pass SM_CYSCREEN constant to GetSystemMetrics to get the Y coordinates of screen.
size.Y = GetSystemMetrics(1);

//We create a compatible bitmap of screen size using screen device context.
hBitmap = CreateCompatibleBitmap(hDC, size.X, size.Y);

//As hBitmap is IntPtr we can not check it against null. For this purspose IntPtr.Zero is used.
if (hBitmap != IntPtr.Zero)
{
//Here we select the compatible bitmap in memeory device context and keeps the refrence to Old bitmap.
IntPtr hOld = (IntPtr)SelectObject(hMemDC, hBitmap);
//We copy the Bitmap to the memory device context.
BitBlt(hMemDC, 0, 0, size.X, size.Y, hDC, 0, 0, SRCCOPY);
//We select the old bitmap back to the memory device context.
SelectObject(hMemDC, hOld);
//We delete the memory device context.
DeleteDC(hMemDC);
//We release the screen device context.
ReleaseDC(GetDesktopWindow(), hDC);
//Image is created by Image bitmap handle and stored in local variable.
Bitmap bmp = Image.FromHbitmap(hBitmap);
//Release the memory to avoid memory leaks.
DeleteObject(hBitmap);
//This statement runs the garbage collector manually.
GC.Collect();
//Return the bitmap
return bmp;
}

//If hBitmap is null return null.
return null;
}