This isn’t tech related…but I am crying here after reading this. No idea if it’s true or not, but it gave me a great laugh on a day when I needed it.
March 30, 2009
November 17, 2008
Color Transitions in Winform Controls
If you’ve ever used web-sites like the hosted WordPress blogs (like this one!) and others, you’ve noticed the new sweet hotness is to have screens give feedback on success or failure of an operation by showing color gradient transitions. The most common is simply “Green to White” (success!) or “Red to Pink” (failure!). This is a quick way to let the user know they can move along and do more work or whether they had an issue. Granted, more detailed logging and/or messages are needed on the “fail” side of things, however since code slingers like us write perfect code all the time….we are just gonna go with quick feedback for now
So, being as I’ve only started in the last few months writing winform/WPF apps, I thought there must be an easy way to do these gradients on forms and other controls quite easily. No so. Sure, there are ForeColor and BackColor properties, however transitioning in a gradient-like fashion from one color to the next isn’t “built in” in any way that I could tell. NOTE: Yes, I’m well aware of the fact that WPF is going to take over the world. But for now this is a Winform app, and until such time as WPF becomes the de-facto standard, it will remain as such. Accordingly, please don’t comment about how WPF can handle this with ease. I know.
So here’s what I came up with:
public static void UpdateColor(Control ctl, Color from, Color to)
{
int step = 1; //Increase if you want the transition to be faster.
var fromT = new Tuple<int, int, int>(
Convert.ToInt32(from.R),
Convert.ToInt32(from.G),
Convert.ToInt32(from.B));
var toT = new Tuple<int, int, int>(
Convert.ToInt32(to.R),
Convert.ToInt32(to.G),
Convert.ToInt32(to.B));
var curT = new Tuple<int, int, int>(fromT);
var done = new Tuple<bool, bool, bool>(false, false, false);
while (true)
{
//Red
if (curT.First >= toT.First)
done.First = true;
else
{
var tempval = curT.First < toT.First ? curT.First += step : curT.First -= step;
curT.First = tempval > toT.First ? toT.First : tempval;
}
//Green
if (curT.Second >= toT.Second)
done.Second = true;
else
{
var tempval = curT.Second < toT.Second ? curT.Second += step : curT.Second -= step;
curT.Second = tempval > toT.Second ? toT.Second : tempval;
}
//Blue
if (curT.Third >= toT.Third)
done.Third = true;
else
{
var tempval = curT.Third < toT.Third ? curT.Third += step : curT.Third -= step;
curT.Third = tempval > toT.Third ? toT.Third : tempval;
}
if (done.First && done.Second && done.Third)
{
ctl.BackColor = to;
ctl.Refresh();
break;
}
ctl.BackColor = Color.FromArgb(curT.First, curT.Second, curT.Third);
ctl.Refresh();
}
}
So, basically I’m just getting the integer values of the RGB color scheme for the from and to colors passed in, looping through adding/subtracting from the start values (from) until I get to the end values (to), refreshing the control along the way. Not too terribly difficult, but interesting none-the-less and quite a nice little UI feature that doesn’t look like most winform applications.
Also, note I’ve added a step variable that you can tweak to adjust how fast or slow the transition occurs. It’s a pretty significant jump from say 1 to 3, so if you want more granular timing, you could adjust the int storage to decimal and account for parts of steps (such as += 0.3). Or you could implement a true timing system that would force the transition to take place within a specific time construct (perhaps the next article on this topic??). But for my needs currently, this is more than sufficient.
And of course, I’m using my handy little Tuple<T1,T2,T3> class, since tuples (or at least the concept of them) rock. Hint hint…please make this concept a part of C# 4.0 Anders…puuuleeeeeease?
public class Tuple<T1,T2,T3>
{
public T1 First { get; set;}
public T2 Second { get; set; }
public T3 Third { get; set; }
public Tuple(T1 t, T2 k, T3 l)
{
First = t;
Second = k;
Third = l;
}
public Tuple(Tuple<T1,T2,T3> t)
{
First = t.First;
Second = t.Second;
Third = t.Third;
}
}
Til next time….keep on slangin!
November 12, 2008
Impersonation & IDisposable
I’ve used an impersonation helper class for a while now, basically to encapsulate changing the current identity context while executing certain code. This worked well, however I always got sick of having to remember to call the “undo()” method of my current implementation once I was done with executing my code under whatever login I was impersonating.
So, I updated the class to implement IDisposable so that I can now utilize this within the using() construct provided in C#. Here’s the class in it’s entirety:
using System;
using System.Runtime.InteropServices;
using System.Security.Principal;
namespace Support.Win32
{
public class Impersonate : IDisposable
{
public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;
WindowsImpersonationContext impersonationContext;
public Impersonate()
{
//Default login is used.
this.impersonateValidUser(“username”, “domain”, “password”);
}
public Impersonate(string username, string domain, string password)
{
this.impersonateValidUser(username, domain, password);
}
[DllImport("advapi32.dll")]
private static extern int LogonUserA(String lpszUserName,
String lpszDomain,
String lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern int DuplicateToken(IntPtr hToken,
int impersonationLevel,
ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool RevertToSelf();
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern bool CloseHandle(IntPtr handle);
private bool impersonateValidUser(string userName, string domain, string password)
{
WindowsIdentity tempWindowsIdentity;
IntPtr token = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
if (RevertToSelf())
{
if (LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, ref token) != 0)
{
if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
if (impersonationContext != null)
{
CloseHandle(token);
CloseHandle(tokenDuplicate);
return true;
}
}
}
}
if (token != IntPtr.Zero)
CloseHandle(token);
if (tokenDuplicate != IntPtr.Zero)
CloseHandle(tokenDuplicate);
return false;
}
private void undoImpersonation()
{
impersonationContext.Undo();
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~Impersonate()
{
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
if(disposing)
{
//Dispose of managed resources.
if(impersonationContext != null)
{
this.undoImpersonation();
impersonationContext.Dispose();
impersonationContext = null;
}
}
}
}
}
Basically, now my code can use the following construct in order to execute code in an impersonated context:
using(var imp = new Impersonate(“username”, “domain”, “password”))
{
//Code that I want to run under this account.
}
October 28, 2008
LINQKit: PredicateBuilder<T> Goodness
Remember the good ol’ days when you wanted to create a query that had dependencies that were unknown at runtime? You’d create a nice StringBuilder instance, and start building your own SQL to handle the complex logic of ever possible permutation that you allowed via your UI. Or you create the hairiest stored procedure known to man with umpteen variables and then tried not only to not screw it up internally, but to make every scenario as fast as possible. Yeah, those days were fun weren’t they?
With LINQ, such tasks are still moderately tough, but now that I’ve found the very nice PredicateBuilder<T> class that comes in the free LINQKit, the ease with which one can create dynamic SQL calls is significantly easier.
As an example, supposed you have a table which contains a description column. And you want to implement a sort of “smart search” on that column such that if your user types in:
Include: Dog Cat
Exclude: Hamster
you code translates that into a query such as:
SELECT * FROM Pets
WHERE Description LIKE ‘%Dog%’
AND Description LIKE ‘%Cat%’
AND Description NOT LIKE ‘%Hamster%’
Behold, PredicateBuilder<T>.
//First get a list of keywords that match the description entered.
string[] parts = txtInclude.Text.Split(new[] {‘ ‘});
string[] noparts = null;
if(txtButNot.Text.Trim().Length > 0)
noparts = txtExclude.Text.Trim().Split(new[] {‘ ‘});
var pred = PredicateBuilder.True<Pet>();
parts.ForEach(p => pred = pred.And(pl => pl.description.Contains(p)));
if(noparts != null)
noparts.ForEach(p => pred = pred.And(pl => !pl.description.Contains(p)));
var pets = from s in db.Pets.Where(pred)
select s;
Notice that it doesn’t matter what order the user types the keywords in, nor does it matter how many there are. Obviously this is a trivial example, and I don’t really have a table that stores pet names
However, I do have some pretty complex requirements to create a way to backtrack and find potential buyers in our system based on previous items they’ve shown interest in. Sounds like a nice use for this gem of a find.
Til next time….keep on slangin!
October 22, 2008
LINQDataSource and Optional Parameters
The combination of LINQDataSource and GridView makes a nice quick way to provide basic search capabilities for your users. Providing a user the ability to search on multiple criteria for a single entity is quick and painless. However, I ran into an issue where one of the columns I was searching by allowed NULL in the table.
My fields looked something like:
<tr>
<td>Company: </td>
<td><asp:TextBox ID=”txtCompNameSearch” runat=”server”></asp:TextBox></td>
</tr>
<tr>
<td>Phone: </td>
<td><asp:TextBox ID=”txtPhoneSearch” runat=”server”></asp:TextBox></td>
</tr>
My LINQDataSource:
<asp:LinqDataSource ID=”ldsCompanies” runat=”server”
ContextTypeName=”DataContext”
TableName=”REG_Companies” EnableUpdate=”True”
Where=”CompanyName.StartsWith(@CompanyName) && Phone.StartsWith(@PhoneNumber)”>
<WhereParameters>
<asp:ControlParameter ConvertEmptyStringToNull=”false” ControlID=”txtCompNameSearch” Name=”CompanyName”
PropertyName=”Text” Type=”String” />
<asp:ControlParameter ConvertEmptyStringToNull=”false” ControlID=”txtPhoneSearch” Name=”PhoneNumber”
PropertyName=”Text” Type=”String” />
</WhereParameters>
</asp:LinqDataSource>
If both CompanyName and Phone fields didn’t allow nulls, this would work just fine. However, like my scenario, the Phone field (for whatever reason) allowed NULL values in the database, this would still work but if you left txtPhoneSearch empty, it would only return records in which the Phone field was NOT NULL.
So, the next logical thing to do would be to change the ConvertEmptyStringToNull value to true for that parameter. Ah, but if you do that you get the following error when you try to load the page the code is on:
No applicable method ‘StartsWith’ exists in type ‘String’
So, this is what I came up with to fix it so you can search optionally on columns that allow nulls using the standard ControlParameter in the LINQDataSource. Leave the ConvertEmptyStringToNull=”false” as you would with non-nullable columns. However, modify your Where clause to the following:
Where=”CompanyName.StartsWith(@CompanyName) && (@PhoneNumber == String.Empty || (@PhoneNumber != String.Empty && Phone.StartsWith(@PhoneNumber)))”>
You’re effectively just giving the query an option to exit early if the @PhoneNumber parameter is empty, but if it is not, then you’re adding the comparison to the dynamic SQL logic.
Til next time….keep on slangin!