C # EventHandler Красивый код (как?) - PullRequest
5 голосов
/ 18 июня 2009

Признаюсь, это немного, но я ищу лучшие способы сделать следующие блоки кода. Они должны быть самоочевидными ...

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

Да, я знаю, это не в срочном порядке. Но мне НЕ нравится (если! = Ноль). Любые магические идеи, чтобы сократить его еще больше: -)

Кстати, я нашел хорошую информацию на похожую тему: Циклы на пустых элементах Приятно читать ...

Ответы [ 8 ]

8 голосов
/ 18 июня 2009

Мне нравится хороший, чистый код, но в большинстве случаев чистый и элегантный не означает короткий и умный. Краткость кода хороша для соревнований. Смена оператора «если не ноль» на foreach может показаться круче, но всем остальным, работающим в проекте, сложнее понять, чего вы пытаетесь достичь. Поверьте мне, даже вы не вспомните это через несколько месяцев: P. Ваш код просто отлично!

3 голосов
/ 18 июня 2009
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();
}
2 голосов
/ 18 июня 2009

Однострочник :

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);
}
1 голос
/ 18 июня 2009

Поскольку вы используете известные события из .NET Framework (в отличие от сторонних) и из кода, похоже, что вы используете эти методы только для определенных классов (например, ListBoxItems и ListBoxes), существует несколько вещей, которые вы знаете , чтобы быть правдой:

  • sender никогда не будет нулевым
  • sender всегда будет ListBoxItem или ListBox, соответственно

Так зачем использовать оператор as? Просто брось!

Тогда первый фрагмент становится

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

Обратите внимание, что это не так в общем случае (вы бы этого не делали, если бы обрабатывали все события PreviewMouseDown в этом одном обработчике для всех типов элементов управления), но для такого кода обработки событий, особенно в коде пользовательского интерфейса, вы можете быть абсолютно уверены, что отправитель не будет нулевым, а отправитель будет того типа, которого вы ожидаете.

0 голосов
/ 18 июня 2009

Используя ту же идею, что и решение Утаала, но в качестве метода расширения ...

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()));
}
0 голосов
/ 18 июня 2009

Вы можете добавить методы расширений к элементам Form, которые затем могут вызывать события:

public static void OnSelectionChanged(this ListBox b, Action<ListBox> a)
{
    b.SelectedIndexChanged += (s,e) =>
    {
        if (s is ListBox)
           a(s as ListBox);           
    };
}
0 голосов
/ 18 июня 2009

Предполагается, что это то же самое, что и первый, немного переформатированный:

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 голосов
/ 18 июня 2009

Возможно, я просто педантичен, но зачем вам разыгрывать отправителя, если вы используете событие в коде его контейнеров хоста.

Независимо от того, кто внес изменения в список, вы не могли бы просто дать вашему списку имя и использовать его.

<ListBox x:Name="listbox1" />

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

Или вы могли бы даже достичь этого, используя привязку без кода.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...