通过DataTemplate为WPF-ComboBoxItem设置TextSearch.Text

Sim*_* D. 6 c# data-binding wpf combobox datatemplate

我使用datatemplate来可视化ComboBox中的一些项目,ItemsSource绑定到ObservableCollection.为了简单起见,让我说我把人放入ObservableCollection:

public class Person {
    public string FirstName { get; set; }
    public string LastName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我的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>
Run Code Online (Sandbox Code Playgroud)

现在我想在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'足够快应该自动提出汉斯彼得.

有解决方案吗

Ant*_*ton 8

简短回答:您想要做的事情不能直接在XAML中完成,但还有其他方法可以做到.

答案很长:ComboBox直接在Items或ItemsSource集合中存储的数据项中查找TextSearch.Text属性.因此,您无法在数据模板或样式中设置属性,因为它们适用于用于显示数据项的对象,而不适用于数据项本身.

特别是,如果查看TextSearch类页面上的示例,您将看到它们将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); } }
}
Run Code Online (Sandbox Code Playgroud)

<ComboBox TextSearch.TextPath="FullName" ItemsSource="collectionOfPersons"/>
Run Code Online (Sandbox Code Playgroud)

另外,如果您不想触摸Person,可以创建一个公开这些属性的包装类.

  • 我担心你是对的.到目前为止,没有为类添加额外的属性,甚至没有为包装和扩展旧类添加额外属性的工作解决方案.由于问题告诉我们这些可能性是已知但不想要的,我不能将其标记为_答案 - 除非你通过一些证据或解释来扩展你的简短答案,为什么这是不可能的. (2认同)

Dre*_*rsh 2

面板周围的东西是默认容器。您需要将 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>
Run Code Online (Sandbox Code Playgroud)