internal static int FindMatchingItems(ItemsControl itemsControl, string text, TextSearchMode mode, int startIndex, out List <int> matchIndexes) { matchIndexes = new List <int>(); ItemCollection items = itemsControl.Items; if (items.Count == 0) { return(-1); } bool isEmptyText = string.IsNullOrEmpty(text); Func <string, bool> isFullMatch; Func <string, bool> isPartialMatch; if (isEmptyText) { isPartialMatch = isFullMatch = (string itemText) => false; } else { isFullMatch = CreateFullMatchFunc(text, mode); isPartialMatch = CreatePartialMatchFunc(text, mode) ?? isFullMatch; } Func <object, object> getTextFunc = null; int fullMatchIndex = -1; for (int i = startIndex; i < items.Count; i++) { object item = items[i]; if (getTextFunc == null && item != null) { getTextFunc = BindingExpressionHelper.CreateGetValueFunc(item.GetType(), GetPrimaryTextPath(itemsControl)); } var container = itemsControl.ItemContainerGenerator.ContainerFromIndex(i) as Control; if (container != null && !container.IsEnabled) { continue; } string primaryText = GetPrimaryText(item, getTextFunc); if (fullMatchIndex < 0 && isFullMatch(primaryText)) { fullMatchIndex = i; matchIndexes.Insert(0, fullMatchIndex); } else if (isPartialMatch(primaryText)) { matchIndexes.Add(i); } } return(fullMatchIndex); }
internal static string GetPrimaryText(object item, string primaryTextPath) { if (item == null) { return(null); } return(GetPrimaryText(item, BindingExpressionHelper.CreateGetValueFunc(item.GetType(), primaryTextPath))); }
private static object GetValueThroughBinding(object item, Binding binding) { BindingExpressionHelper helper = new BindingExpressionHelper(); try { helper.DataContext = item; BindingOperations.SetBinding(helper, ValueProperty, binding); return(helper.GetValue(ValueProperty)); } finally { helper.ClearValue(BindingExpressionHelper.ValueProperty); } }
/// <summary> /// Returns a Func that will return the value of the property, specified by the provided propertyPath. /// </summary> /// <param name="itemType">The type of the instance which property will be returned.</param> /// <param name="propertyPath">The path of the property which value will be returned.</param> public static Func <object, object> CreateGetValueFunc(Type itemType, string propertyPath) { if (propertyPath != null && propertyPath.IndexOfAny(new char[] { '.', '[', ']', '(', ')' }) > 0) { return((item) => BindingExpressionHelper.GetValueThroughBinding(item, propertyPath)); } var parameter = System.Linq.Expressions.Expression.Parameter(itemType, "item"); System.Linq.Expressions.Expression get; if (string.IsNullOrEmpty(propertyPath)) { get = parameter; } else { try { get = System.Linq.Expressions.Expression.PropertyOrField(parameter, propertyPath); } catch (ArgumentException) { get = System.Linq.Expressions.Expression.Constant(null); } } var lambda = System.Linq.Expressions.Expression.Lambda(get, parameter); var compiled = lambda.Compile(); var methodInfo = typeof(BindingExpressionHelper) .GetMethod("ToUntypedFunc", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static) .MakeGenericMethod(new[] { itemType, lambda.Body.Type }); return((Func <object, object>)methodInfo.Invoke(null, new object[] { compiled })); }