Archives for : October2008

Had some trouble with using a converter when databinding on a GridView yesterday so I thought I’d do a quick write up.

Imagine for one instance you have the following class:

public class EntityDataItem
{
    public string Name { get; set; }
    public string Type { get; set; }
    public DateTime CreatedTS { get; set; }
}

Now imagine you have the following xaml:

<ListView Name="EntitiesGrid">
<ListView.View>
<GridView>
<GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"/>
<GridViewColumn Header="Type" DisplayMemberBinding="{Binding Type}"/>
<GridViewColumn Header="CreatedTS" DisplayMemberBinding="{Binding CreatedTS}"/>
</GridView>
</ListView.View>
</ListView>

To bind to the grid all you would have to do on the window load event is:

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    List<EntityDataItem> items = new List<EntityDataItem>();
    items.Add(new EntityDataItem { Name = "A", Type = "Person", CreatedTS = DateTime.Now });
    items.Add(new EntityDataItem { Name = "B", Type = "Equipment", CreatedTS = DateTime.Now });
    items.Add(new EntityDataItem { Name = "C", Type = "Location", CreatedTS = DateTime.Now });
    items.Add(new EntityDataItem { Name = "D", Type = "Unit", CreatedTS = DateTime.Now });
    EntitiesGrid.ItemsSource = items;
}

Well now, that’s all fine and good. But now imagine you were, oh, I don’t know, working on some military project that wanted you do use a specific format for the date. The way it is now when the binding happens it will use the default ToString() which isn’t acceptable in this case.

So we need to use a converter. Converters let you go from any object to any object on databinding. Let’s start by creating the converter:

[ValueConversion(typeof(DateTime), typeof(String))]
public class DateToMilitaryConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null)
            return "";
        DateTime date = (DateTime)value;
        return date.ToString("dd MMM yyyy HHmm", DateTimeFormatInfo.InvariantInfo);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        string strValue = value.ToString();
        DateTime resultDateTime;
        if (DateTime.TryParse(strValue, out resultDateTime))
        {
            return resultDateTime;
        }
        return value;
    }
}

then in the resources for your xaml define:

<local:DateToMilitaryConverter x:Key="dateConverter"/>

assuming the local namespace is defined as your local assembly or whatever namespace you used for the converter.

Here’s where things get a bit tricky. You can’t put a converter directly on a GridViewColumn. Where you can put it is on the Binding. To do that make your xaml look like:

<ListView Name="EntitiesGrid">
    <ListView.View>
        <GridView>
            <GridViewColumn Header="Name" DisplayMemberBinding="{Binding Name}"/>
            <GridViewColumn Header="Type" DisplayMemberBinding="{Binding Type}"/>
            <GridViewColumn Header="CreatedTS">
                <GridViewColumn.DisplayMemberBinding>
                    <Binding Path="CreatedTS" Converter="{StaticResource dateConverter}"/>
                </GridViewColumn.DisplayMemberBinding>
            </GridViewColumn>
        </GridView>
    </ListView.View>
</ListView>

You can see here we are tapping into the DisplayMemberBinding propery of the GridViewColumn and assigning a Binding to it. On the Binding we can use a converter. As I mentioned though you can go from any object to any other object. Remember, however, regardless of what you go to, the ToString() will be called on it. A couple of points of interest on the converter. The source of the data in the real binding, not my contrived example, is a DateTime? which means the value could be null. Thus I have accounted for that in the converter. Additionally I allow for a class cast exception rather then doing:

DateTime date = value as DateTime;
if (value == null)
    return "";

in case someone else were to use my class where it doesn’t belong. Basically the converter handles DateTime? but nothing else, as it should be.

Well, I meant this one to be short and sweet and it was.

Later,
Brian

UPDATE:
It has been brought to my attention that you can do converters inline with the DisplayMemberBinding.

<GridViewColumn 
    Header="CreatedTS" 
    DisplayMemberBinding="{Binding Path=CreatedTS, Converter={StaticResource dateConverter}}"
/>

Live and learn 🙂
Brian

Did You Know?

Interesting video here.

http://release.theplatform.com/content.select?pid=x7aVOMrlfkkijQwcLllwk6WjB5JE0zrF

I haven’t fact checked everything in this (since it’s obviously not mine) so use your own head in accepting the facts as they are portrayed. It’s still interesting.

Brian

T1, T2, T3, T4, TResult, Hut, Hut, Hike

This post is kind of not LINQ related, kind of LINQ related.

I’ve mentioned lambdas before but wanted to move more into what is more at the core of lambdas. That is more along the lines of delegates.

We all know about delegates, don’t we?

“No Brian, we don’t.”

“Ivan is that you?” (Yes, I’ve named my inner voice Ivan, IV, inner voice, Ivan, get it?)

“Yes”

“Um, is that all?”

“What else do you want me to say? I want to know about delegates”

Ok, well, then, delegates are basically pointers to methods.

Let me give you an example:

public partial class Window1 : Window
{
    delegate int del(int i);

    public Window1()
    {
        del myDelegate = x => x * x;
        int square = myDelegate(5);
    }
}

You can see here that I have defined my type for the delegate below the class declaration

delegate int del(int i);

The delegate, myDelegate, takes an int and returns an int. Then inline with anycode I can define a method that uses these parameters.

Now I could do something like:

del myDelegate2 = x => --x;
int decrement = myDelegate2(4);

but without having to declare a delegate type let’s take a look at Func so we can create functions inline without having to declare a delegate type first. We technically are declaring a type because of generics and we are limited to the small set of parameters that Func allows us, but that’s neither here nor there since I would assume, for an inline query this should be able to handle your needs. If you can’t do it in what Func provides I suspect you will probably just do a standard method.

Func types are:

Func(TResult) Delegate
Func(T, TResult) Delegate
Func(T1, T2, TResult) Delegate
Func(T1, T2, T3, TResult) Delegate
Func(T1, T2, T3, T4, TResult) Delegate

So let’s take a look at some code:

int[] list1 = { 0, 1, 2, 3, 4, 5 };
Func<int, bool> lookForEven = x => x % 2 == 0;
var myListOfEvens = list1.Where(lookForEven);

The Where method in the int list takes Func<int, bool> predicate. (It will take Func<int, int, bool> predicate as well). So I created the method lookForEven with a lambda, x => x % 2 == 0, and then I can use it in the Where method. Now, the operations of the method don’t have to be defined inline. They can be a method that matches the types of the declaration.

private bool BadlyNamedMethod(int val)
{
    return Math.Pow(val, 2) < 20;
}

private void TestMyMethod()
{
    int[] list1 = { 0, 1, 2, 3, 4, 5 };
    var sqrsLessThenTwenty = list1.Where(BadlyNamedMethod);
}

Now let’s look at taking multiple inputs:

int[] list1 = { 0, 1, 2, 3, 4, 5 };
int[] list2 = { 0, 2, 4, 6, 8 };
Func<int, int, bool> myFunc = (x,y) => x == y;
foreach (var x in list1)
{
    foreach (var y in list2)
    {
        if (myFunc(x, y))
        {
            MessageBox.Show("Found Match");
            break;
        }
    }
}

Basically I’m creating an intersect.

“Brian, there is an intersect function already.”

“Yes Ivan, I know”

“Fine, f-off”

Yes, yes, yes, as Ivan pointed out I could just as easily done:

var myListOfEquals = list1.Intersect(list2);

but then you wouldn’t see me using the Func.

Basically, I’m creating a function that takes two parameters, x and y, and testing for equality. The system knows what I’m going to do becuase when I created “myFunc” I defined that it would take int, int and return bool.

But we’re not limited to primitives.

private void TestMyMethod()
{
    Person[] people = {new Person {FirstName = "Brian", LastName = "Mullen", Id = 1},
			   new Person {FirstName = "George", LastName = "Smith", Id = 2},
			   new Person {FirstName = "Mabel", LastName = "Jones", Id = 3}};

    Func<Person, string> compareByName = p => p.LastName;
    var orderedByLastName = people.OrderBy(compareByName);
}

Want to compare people by a list of strings?

Func<Person, string, int?> personCompare = (x, y) =>
{
    if (x.FirstName == y)
        return x.Id;
    return null;
};

Anyways, have to go. But hopefully this is a nice introductory look to delegates, Func and some lambdas.

Brian

UpdateOrInsert (Upsert)

Hibernate used an InsertOrUpdate (aka Upsert) method to save values (netTiers uses Save for the same thing).  This made things really simple, no need to work out if you have inserted the object, just call InsertOrUpdate and Bob’s your uncle.  Here I present the InsertOrUpdate method (well, copied from http://blogs.msdn.com/miah/archive/2008/02/17/sql-if-exists-update-else-insert.aspx but I made it universally applicable 🙂 .  A handy little thing that lets you use do both.

(MS SQL)

UPDATE Table1 SET (...) WHERE Column1='SomeValue'
IF @@ROWCOUNT=0
   INSERT INTO Table1 VALUES (...)

It’s nice, it’s simple and does what needs to be done without a lot of work. 

Here is the same approach can be used for postgresql, oracle and mysql.

(PostgreSQL)

UPDATE Table1 SET (...) WHERE Column1='SomeValue'
IF NOT FOUND
   INSERT INTO Table1 VALUES (...)

(Oracle)

UPDATE Table1 SET (...) WHERE Column1='SomeValue'
IF sql%rowcount=0
   INSERT INTO Table1 VALUES (...)

(MySQL)

INSERT INTO Table1 (Column1, ...) VALUES (SomeValue, ...)
ON DUPLICATE KEY UPDATE ...

See also:

http://blog.cutterscrossing.com/index.cfm/2008/2/4/SQL-Tricks-Whats-an-Upsert

UPDATE: Btw, if you’re using SQL Server 2008 you can use MERGE to do this.