Dim dict As New Collections.Generic.Dictionary(Of String,String) Private Sub MainWindow_Loaded() Handles Me.Loaded dict.Add("One","1") dict.Add("Two","2") dict.Add("Three","3") lst1.ItemsSource = dict End Sub
在表单上我有一个ListBox(名为“lst1”),它使用“dict”作为项目源:
<ListBox x:Name="lst1"> <ListBox.ItemTemplate> <DataTemplate> <Label Content="{Binding Value}" TextSearch.Text="{Binding Path=Key,Mode=OneWay}" /> </DataTemplate> </ListBox.ItemTemplate> </ListBox>
我还有一个非绑定的ListBox,手动预先填充值:
<ListBox> <Label TextSearch.Text="One" Content="1" /> <Label TextSearch.Text="Two" Content="2" /> <Label TextSearch.Text="Three" Content="3" /> </ListBox>
因此,当我启动应用程序时,它看起来像这样:
问题:
如果我尝试通过键入“one”,“two”或“three”来使用键盘导航项目,我只能在非绑定列表框中成功.绑定列表框失败.
一些评论:
1.)如果我在绑定列表框中按“[”,焦点会以循环方式从一个项目改变到另一个项目:它从1到2,从2到3,从3到1,再从1再到2等.
2.)我已经使用Snoop检查了应用程序.我在绑定和非绑定列表框之间找到了一个区别.两个列表框都在Label控件上设置TextSearch.Text属性(在ItemsPresenter内).但对于非约束情况:TextSearch.Text属性的“值源”是“Local”.对于约束情况:“value source”是“ParentTemplate”.
附: (和N.B.)
我知道我可以在列表框中使用TextSearch.TextPath,但这不是我需要的:)
另外,为ListViewItem设置TextSearch.Text属性(通过使用Style)也无济于事.
解决方法
TextSearch的实现枚举ItemsSource属性的实际数据项,并直接查看它们以读取Text依赖项属性.当您将ListBoxItems放在其中时,就像在您的示例中一样,它可以工作,因为实际项是ListBoxItem实例,并且Text依赖属性“附加”到它们.绑定到词典后<>它现在直接关注KeyValuePair<>不是DependencyObjects的实例,因此不能/不具有TextSearch.Text属性.这也是为什么通过ItemContainerStyle在ListBoxItem上设置TextSearch.Text属性没有效果的原因:ItemContainerStyle描述了数据在可视树中的外观,但TextSearch引擎只考虑原始数据源.如何在UI中设置数据样式并不重要,这就是为什么修改DataTemplate永远不会为TextSearch做任何事情.
另一种方法是创建一个视图模型类,该类继承自DependencyObject,您可以根据要搜索的值在其上设置TextSearch.Text附加属性.下面是一些示例代码,说明了这将如何工作:
private sealed class MyListBoxItem : DependencyObject { public static readonly DependencyProperty KeyProperty = DependencyProperty.Register("Key",typeof(string),typeof(MyListBoxItem),new FrameworkPropertyMetadata(string.Empty)); public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value",new FrameworkPropertyMetadata(string.Empty)); public string Key { get { return (string)GetValue(KeyProperty); } set { SetValue(KeyProperty,value); SetValue(TextSearch.TextProperty,value); } } public string Value { get { return (string)GetValue(ValueProperty); } set { SetValue(ValueProperty,value); } } } // Assign a list of these as the list Box's ItemsSource this.listBox.ItemsSource = new List<MyListBoxItem> { new MyListBoxItem { Key = "One",Value = "1" },new MyListBoxItem { Key = "Two",Value = "2" },new MyListBoxItem { Key = "Three",Value = "3" } };
ListBox定义如下所示:
<ListBox Name="listBox"> <ListBox.ItemTemplate> <DataTemplate> <TextBlock Text="{Binding Value}" /> </DataTemplate> </ListBox.ItemTemplate> </ListBox>
任何其他替代方案都需要您使用TextSearch.TextPath,但您似乎已经死了.如果您接受修改DataTemplate将永远不会工作,我建议的解决方案是简单地创建一个POCO视图模型,其中包含您要用于搜索的属性并将其指定给TextSearch.TextPath.它是实现你正在做的事情中最轻的,非黑客的方式.