2009-06-17 52 views
5

我承认,它是一种微小的,但我正在寻找更好的方法来做下面的代码块。他们应该是自我解释...C#EventHandler美丽的代码(如何?)

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(); 
      } 
     } 
    } 

再丑之一:

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

是啊,我知道,它不是濒死紧急。但我不喜欢(如果!= null)。任何神奇的想法,缩短甚至更多:-)

顺便说一句,我发现关于类似的话题了一些不错的信息:Loops on Null Items 尼斯读...

回答

3
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(); 
} 
0

也许我只是被迂腐但为什么你需要如果您在其主机容器代码中使用该事件,则可以投送发件人。

无论谁对列表进行了更改,是否可以给列表框添加一个名称并使用它。

<ListBox x:Name="listbox1" /> 

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

或者你甚至可以实现一些使用绑定,没有代码背后。

+0

这个问题的唯一目的就是吹毛求疵:-)但还不错的主意,将在进一步考虑节目。说实话,我认为我接近良好的做法,但你永远不会知道...... – 2009-06-17 23:57:16

0

这应该是一样的第一个,重新格式化一点点:

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

您可以添加扩展方法来形成元素,这样就可以触发事件:

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

一衬垫

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

,或者嵌套:

private void listBoxItem_PreviewMouseDown(object sender, MouseButtonEventArgs e) 
{ 
    As<ListBoxItem>(sender, (listBoxItem) => { 
     As<ClickObject>(listBoxItem.DataContext, 
      (clickObject) => clickObject.SingleClick()); 
    }; 
} 
使用这种静态的通用方法

(T是目标类型,输入为对象投射,码是一个代表(或λ表达),以对成功执行:

static void As<T>(object input, Action<T> code) where T : class 
{ 
    T foo = input as T; 
    if (foo != null) 
    code(foo); 
} 
+0

打我吧:) – 2009-06-18 00:34:50

+0

有趣的方法...这个例子有点复杂(甚至不知道这是可能)但很高兴知道! – 2009-06-18 00:39:09

8

我爱好,清洁代码,但在大多数情况下,优雅并不意味着简洁和智能。代码简洁有利于竞争。将“if not null”语句更改为foreach可能看起来更酷,但在项目中工作的每个人都很难理解您要完成的任务。相信我,即使你几个月后不会记得它:P。你的代码很好,因为它是!

+1

+1这是一个梦幻般的答案。 – 2009-06-18 00:44:16

1

由于您使用的.NET框架(而不是第三方)的已知事件,并从代码看起来像你只使用这些方法的特定类(即ListBoxItems和ListBoxes),有你知道的几件事情是真实的:

  • sender永远不会为空
  • sender永远是一个ListBoxItem,或列表框,分别为

那么为什么要使用as运算符?只需投!

然后第一个片段成为

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

注意,这不是在一般情况下,真正的(你不会做,如果你正在处理中的一个处理所有PreviewMouseDown事件对所有的控件类型)但对于像这样的事件处理代码,尤其是在UI代码中,您可以确定任何事情,发件人不会为空,并且发件人的类型与您期望的类型相同。

0

使用相同的思路Utaal的解决方案,但作为一个扩展方法...

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())); 
}