AutoCompleteBox - 如何 select 匹配项目集合中的特定项目?
AutoCompleteBox - How to select a specific item from a collection of matching items?
使用 AutoCompleteBox 时 - 我有一个具有匹配显示文本但 ID 值不同的项目列表。
[{Text:"John",Id:1},{Text:"John",Id:2},{Text:"John Doe",Id:3}]
当我 select 第二行 (John #2) - 第一个值 (John #1) 设置为 SelectedItem
属性。当 selecting 一个不同的值时 (John Doe #3) - 它工作正常。
我的观察是,如果有更多匹配项目 - 它总是取第一个。
我该怎么做才能将正确的项目 (John #2) 设置为 SelectedItem?
<controls2:AutoCompleteBox
EraseTextIfNull="False"
ValueMemberBinding="{Binding Converter={StaticResource AutocompleteItemTextConverter}}"
ItemsSource="{Binding TestItemSource, RelativeSource={RelativeSource TemplatedParent}}"
SelectedItem="{Binding TestSelectedItem,Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
Text="{Binding TestText, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
ItemTemplate="{Binding Source={StaticResource TestItemTemplate}}"
/>
视图模型:
public class TestItemDto
{
public int Id { get; set; }
public string Text { get; set; }
}
private ObservableCollection<TestItemDto> _testItemSource = new ObservableCollection<TestItemDto>
{
new TestItemDto
{
Id = 1,
Text = "John"
},
new TestItemDto
{
Id = 2,
Text = "John"
},
new TestItemDto
{
Id = 3,
Text = "John Doe"
},
};
public ObservableCollection<TestItemDto> TestItemSource
{
get => _testItemSource;
set
{
_testItemSource = value;
}
}
private string _testText;
public string TestText
{
get { return _testText; }
set
{
_testText = value;
Console.WriteLine($"TestText:{TestText}");
}
}
private TestItemDto _testSelectedItem;
public TestItemDto TestSelectedItem
{
get { return _testSelectedItem; }
set
{
_testSelectedItem = value;
Console.WriteLine($"TestText:{TestSelectedItem?.Id}:{TestSelectedItem?.Text}");
}
}
转换器:
public class AutocompleteItemTextConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var adresarSearchResultItemDto = value as TestItemDto;
return adresarSearchResultItemDto?.Text;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
问题出在 TryGetMatch
搜索匹配文本然后选择第一个匹配项的方法。
我添加了一个 priorityView
参数(其中传递了 SelectedItem
)。因此,在搜索 ItemSource 的其余部分之前 - 首先它会检查当前 SelectedItem 是否已经匹配文本:
private object TryGetMatch(string searchText, object priorityView,ObservableCollection<object> view, AutoCompleteFilterPredicate<string> predicate)
{
if (priorityView != null)
{
if (predicate(searchText, FormatValue(priorityView)))
{
return priorityView;
}
}
if (view != null && view.Count > 0)
{
foreach (object o in view)
{
if (predicate(searchText, FormatValue(o)))
{
return o;
}
}
}
return null;
}
这也merged到原始存储库
使用 AutoCompleteBox 时 - 我有一个具有匹配显示文本但 ID 值不同的项目列表。
[{Text:"John",Id:1},{Text:"John",Id:2},{Text:"John Doe",Id:3}]
当我 select 第二行 (John #2) - 第一个值 (John #1) 设置为 SelectedItem
属性。当 selecting 一个不同的值时 (John Doe #3) - 它工作正常。
我的观察是,如果有更多匹配项目 - 它总是取第一个。
我该怎么做才能将正确的项目 (John #2) 设置为 SelectedItem?
<controls2:AutoCompleteBox
EraseTextIfNull="False"
ValueMemberBinding="{Binding Converter={StaticResource AutocompleteItemTextConverter}}"
ItemsSource="{Binding TestItemSource, RelativeSource={RelativeSource TemplatedParent}}"
SelectedItem="{Binding TestSelectedItem,Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
Text="{Binding TestText, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
ItemTemplate="{Binding Source={StaticResource TestItemTemplate}}"
/>
视图模型:
public class TestItemDto
{
public int Id { get; set; }
public string Text { get; set; }
}
private ObservableCollection<TestItemDto> _testItemSource = new ObservableCollection<TestItemDto>
{
new TestItemDto
{
Id = 1,
Text = "John"
},
new TestItemDto
{
Id = 2,
Text = "John"
},
new TestItemDto
{
Id = 3,
Text = "John Doe"
},
};
public ObservableCollection<TestItemDto> TestItemSource
{
get => _testItemSource;
set
{
_testItemSource = value;
}
}
private string _testText;
public string TestText
{
get { return _testText; }
set
{
_testText = value;
Console.WriteLine($"TestText:{TestText}");
}
}
private TestItemDto _testSelectedItem;
public TestItemDto TestSelectedItem
{
get { return _testSelectedItem; }
set
{
_testSelectedItem = value;
Console.WriteLine($"TestText:{TestSelectedItem?.Id}:{TestSelectedItem?.Text}");
}
}
转换器:
public class AutocompleteItemTextConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var adresarSearchResultItemDto = value as TestItemDto;
return adresarSearchResultItemDto?.Text;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
问题出在 TryGetMatch
搜索匹配文本然后选择第一个匹配项的方法。
我添加了一个 priorityView
参数(其中传递了 SelectedItem
)。因此,在搜索 ItemSource 的其余部分之前 - 首先它会检查当前 SelectedItem 是否已经匹配文本:
private object TryGetMatch(string searchText, object priorityView,ObservableCollection<object> view, AutoCompleteFilterPredicate<string> predicate)
{
if (priorityView != null)
{
if (predicate(searchText, FormatValue(priorityView)))
{
return priorityView;
}
}
if (view != null && view.Count > 0)
{
foreach (object o in view)
{
if (predicate(searchText, FormatValue(o)))
{
return o;
}
}
}
return null;
}
这也merged到原始存储库