2010-12-28 3 views
4

в моем приложении WPF Я использовал для динамического добавления элементов управления в холст. Формат имени элемента управления - «Control_UniqueValue».Lambda выражение возвращает ноль, если null

то есть, если я добавить первый элемент управления на холст, то название будет «Control_1» и дальше будет «Control_2» и т.д ...

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

я использовал следующее заявление для этого

string maxId = (string)canvas1.Children.Cast<FrameworkElement>().ToList().Max(x => (x.Name.Substring(x.Name.LastIndexOf('_') + 1))); 

, но проблема здесь

  1. необходимо вернуть значение, как INT

  2. если полотно не содержит элементов управления он поднимет ошибку (попытался с помощью Nullable типа, но не смог)

ответ

4
int maxId = canvas1.Children 
    .Cast<FrameworkElement>() 
    .Select(e => int.Parse(e.Name.Substring(e.Name.LastIndexOf('_')))) 
    .DefaultIfEmpty() 
    .Max(); 

Это должно возвращать 0 вместо того, чтобы бросать исключение, если в последовательности нет элементов. Кроме того, звонок в ToList в вашем коде не требуется. Это все равно будет выдавать исключение, если какое-либо из имен управления не находится в ожидаемом формате.

4

Чтобы получить целое число, вы можете использовать int.Parse метод. Вам не нужно звонить ToList().

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

Вы можете использовать метод DefaultIfEmpty расширения, чтобы обеспечить значение по умолчанию, если последовательность пуста:

int maxId = canvas1.Children 
      .Cast<FrameworkElement>() 
      .DefaultIfEmpty(new FrameworkElement() { Name = "Control_0" }) 
      .Max(x => (int.Parse(x.Name.Split('_')[1]) + 1))); 
+0

Аргументы типа для метода 'System.Linq.Enumerable.DefaultIfEmpty (System.Collections.Generic.IEnumerable , TSource)' не может быть выведенным из использования. Попробуйте явно указать аргументы типа. – Binil

+0

Я отредактировал свой ответ. Вы должны указать экземпляр класса FrameworkElement в качестве значения по умолчанию для пустого списка причин. – Jan

3

С Max() требует, по меньшей мере, один элемент в своей последовательности вы должны либо

  • поймать исключение и установить max на ноль
  • проверить длину перед вызовом Max(). Я рекомендовал бы этот

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

private int NumberFromElementName(string name) 
{ 
    // Or search for the last '_' using name.LastIndexOf() 
    var numString = name.Substring("Control_".Length); 
    return Int32.Parse(numString); 
} 

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

var children = canvas1.Children.OfType<FrameworkElement>().ToArray(); 
int max = 0; 
if (children.Length > 0) 
    max = children.Max(x => NumberFromElementName(x.Name)); 
string nextChildName = String.Format ("Control_{0}", max + 1); 

EDIT: Как отметил @Jan в своем ответе, вы можете избежать разделения запроса на две части с помощью DefaultIfEmpty перед Максом вызов в запросе.

0

получил окончательный ответ

int maxId = canvas1.Children .Cast<FrameworkElement>() .Select(e => int.Parse(e.Name.Substring(e.Name.LastIndexOf('_')+ 1))) .DefaultIfEmpty() .Max(x => x + 1); 

Благодаря Jan & Ли

Смежные вопросы