我使用datatemplate来可视化ComboBox中的一些项目, ItemsSource绑定到ObservableCollection。 为了简单起见,假设我将人员纳入ObservableCollection:
public class Person {
public string FirstName { get; set; }
public string LastName { get; set; }
}
我的DataTemplate看起来像这样:
<DataTemplate TargetType="{x:Type Person}">
<StackPanel Orientation="Horizontal">
<TextSearch.Text>
<MultiBinding StringFormat="{} {0} {1}">
<Binding Path="FirstName"/>
<Binding Path="LastName"/>
</MultiBinding>
</TextSearch.Text>
<TextBlock Text="{Binding FirstName}" Margin="2,0" />
<TextBlock Text="{Binding LastName}"/>
</StackPanel>
</DataTemplate>
现在我想在ComboBox中为全名启用自动完成功能,而不在我的person类上引入第三个属性。因此我不想在ComboBox上使用TextSearch.TextPath属性,而是想在DataTemplate中绑定每个ComboBoxItem的TextSearch.Text-Property。 不幸的是,当我这样做(使用MultiBinding和StringFormat,使用Snoop测试)时,绑定值仅为我的StackPanel注册,但是使用Snoop(很棒的工具)我发现这个stackpanel就像其他一些ComboBoxItemTemplate的内容一样,它放置另一个边框等,最后一个ComboBoxItem标签围绕我的外部StackPanel。因此,TextSearch.Text设置无效,因为它必须在创建的ComboBoxItem中设置,而不是在其中的某个位置。
现在问题:如何使用XAML-Styles和-Control-Templates将我的DataTemplate中的TextSearch.Text-Property传播到周围的ComboBoxItem? 该解决方案可能会修改ComboBox和ComboBoxItem的默认ControlTemplates以及我的自定义(Item-)DataTemplate,但不会使用任何Code-Behind,或者至少不会太多。也许附加的行为也可以。但我几乎肯定必须有一种方法可以使它无需工作,TemplateBinding或RelativeSource-stuff ... 当然,解决方案必须使我的键盘选择和文本完成工作,s。如果名单中包含汉斯约瑟夫和汉斯彼得,那么进入'汉斯'应该自动提出汉斯约瑟夫,而快速进入'汉斯P'应该自动提出汉斯彼得。
任何解决方案?
答案 0 :(得分:8)
简短回答:您想要做的事情不能直接在XAML中完成,但还有其他方法可以做到。
答案很长:ComboBox直接在Items或ItemsSource集合中存储的数据项中查找TextSearch.Text属性。因此,您无法在数据模板或样式中设置属性,因为它们适用于用于显示数据项的对象,而不适用于数据项本身。
特别是,如果查看TextSearch class页面上的示例,您将看到它们将TextSearch.Text属性附加到进入ComboBox.Items集合的Image对象。您可以通过使Person成为DependencyObject在您的程序中执行此操作,但我认为您不希望在每个对象上设置该属性。
这里有几个选项:
如果可以修改Person类,则可以定义ToString()方法以将文本返回到自动完成,或者定义像Fullname这样的任意属性,并在ComboBox上设置Textsearch.TextPath。例如:
public class Person
{
string FirstName { get; set; }
string LastName {get; set; }
string FullName { get { return String.Format("{0} {1}", FirstName, LastName); } }
}
和
<ComboBox TextSearch.TextPath="FullName" ItemsSource="collectionOfPersons"/>
另外,如果您不想触摸Person,可以创建一个公开这些属性的包装类。
答案 1 :(得分:1)
面板周围的东西是默认容器。您需要将TextSearch.Text属性应用于容器。您应该可以通过ItemContainerStyle设置属性,如下所示:
<ComboBox.ItemContainerStyle>
<Style TargetType="{x:Type ComboBoxItem}">
<Setter Property="TextSearch.Text">
<Setter.Value>
<MultiBinding StringFormat="{} {0} {1}">
<Binding Path="FirstName"/>
<Binding Path="LastName"/>
</MultiBinding>
</Setter.Value>
</Setter>
</Style>
</ComboBox.ItemContainerStyle>