views:

509

answers:

8

Hi, I admit, it is kind of tiny, but I am looking for better ways to do the following code blocks. They should be self explaining...

    private void listBoxItem_PreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
        var listBoxItem = sender as ListBoxItem;
        if (listBoxItem != null)
        {
            var clickObject = listBoxItem.DataContext as ClickObject;
            if (clickObject != null)
            {
                clickObject.SingleClick();
            }
        }
    }

Another ugly one:

    private void listBox_SelectionChangedA(object sender, SelectionChangedEventArgs e)
    {
        var lB = sender as ListBox;
        if (lB != null)
            StatusBoxA.Text = "Elements selected" + lB.SelectedItems.Count;
    }

Yeah, I know, its not near-death-urgent. But I do NOT like the (if != null). Any magic ideas to shorten it even more :-)

Btw, I found some nice info about a similar topic: Loops on Null Items Nice to read...

A: 

Maybe I am just being pedantic but why do you need to cast the sender if you are using the event within its host containers code.

Regardless of who made the change to a list, couldn't you just give your listbox a name and use that.

<ListBox x:Name="listbox1" />

private void listBox_SelectionChangedA(object sender, SelectionChangedEventArgs e)
{
    StatusBoxA.Text = "Elements selected" + listbox1.SelectedItems.Count;
}

Or you could even achieve some of this using binding with no code behind.

benPearce
The only purpose of this question is hairsplitting :-) But also good idea, will be considered in further programming. To be honest, I think I am close to good practice, but you'll never know...
Christian
A: 

This is supposed to be the same as the first one, reformatted a little:

private void listBoxItem_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
    ClickObject clickObject;
    if (
        ((sender as ListBoxItem) != null) &&
        ((clickObject = ((ListBoxItem)sender).DataContext as ClickObject) != null)
        )
    {
        clickObject.SingleClick();
    }
}
ChrisW
A: 

You can add extensions methods to Form elements, which can then trigger the events:

public static void OnSelectionChanged(this ListBox b, Action<ListBox> a)
{
    b.SelectedIndexChanged += (s,e) =>
    {
        if (s is ListBox)
           a(s as ListBox);           
    };
}
eulerfx
+1  A: 

One-liner:

private void listBox_SelectionChangedA(object sender, SelectionChangedEventArgs e)
{
    As<ListBox>(sender, (lB) => StatusBoxA.Text = "Elements selected" + lB.SelectedItems.Count);
}

or, nested:

private void listBoxItem_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
    As<ListBoxItem>(sender, (listBoxItem) => {
        As<ClickObject>(listBoxItem.DataContext,
            (clickObject) => clickObject.SingleClick());
    };
}

using this static generic method (T is destination type, input is object to cast, code is a delegate (or lambda expression) to execute on success:

static void As<T>(object input, Action<T> code) where T : class
{
  T foo = input as T;
  if (foo != null)
  code(foo);
}
Utaal
Beat me to it :)
Cameron MacFarland
Interesting approach... A little to sophisticated for this example (didn't even know this is possible) but definitly nice to know !!
Christian
+5  A: 

I love good, clean code but in most cases, clean & elegant doesn't mean short and smart. Code brevity is good for competitions. Changing an "if not null" statement to a foreach might seem way cooler but it's harder for everyone else working in the project to understand what you are trying to accomplish. Believe me, even you won't remember it a few months later :P. Your code is just fine as it is!

Diadistis
+1 This is a fantastic answer.
Andrew Hare
+1  A: 

Since you're using known events from the .NET framework (as opposed to a third party) and from the code it looks like you're only using those methods for specific classes (i.e. ListBoxItems and ListBoxes), there are a few things you know to be true:

  • sender will never be null
  • sender will always be a ListBoxItem, or ListBox, respectively

So why use the as operator? Just cast!

Then the first snippet becomes

private void listBoxItem_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
        var listBoxItem = (ListBoxItem)sender;
        var clickObject = (ClickObject)listBoxItem.DataContext;
        clickObject.SingleClick();
}

Note this isn't true in the general case (you wouldn't do this if you were handling all PreviewMouseDown events in that one handler for all Control types), but for event handling code like this, especially in UI code, you can be as certain as you can be of anything, that sender will not be null and sender will be of the type you expect.

ageektrapped
+2  A: 
private void listBoxItem_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
        var listBoxItem = sender as ListBoxItem;
        if (listBoxItem == null) return;

        var clickObject = listBoxItem.DataContext as ClickObject;
        if (clickObject == null) return;

        clickObject.SingleClick();
}
Sergey Aldoukhov
It looks much nicer then my code :-)
Christian
A: 

Using the same idea as Utaal's solution, but as an extension method...

public static void As<TSource>(this object item, Action<TSource> action) where TSource : class
{
    var cast = item as TSource;

    if (cast != null)
        action(cast);
}

private void listBoxItem_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
    sender.As<ListBoxItem>(listBoxItem => 
        listBoxItem.DataContext.As<ClickObject>(clickObject =>
            clickObject.SingleClick()));
}
Cameron MacFarland