7

我使用数据模板来可视化 ComboBox 中的一些项目,ItemsSource 绑定到 ObservableCollection。为简单起见,假设我将人员放入 ObservableCollection:

public class Person {
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

我的数据模板看起来像这样:

<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 的内容,它会在我的外部 StackPanel 周围放置另一个边框等,最后是 ComboBoxItem-tag。因此,TextSearch.Text-setting 无效,因为它必须设置在创建的 ComboBoxItem 中,而不是其中的某个位置。

现在提问:如何仅使用 XAML-Styles 和 -Control-Templates 将此 TextSearch.Text-Property 从我的 DataTemplate 传播到周围的 ComboBoxItem?该解决方案可能会修改 ComboBox 和 ComboBoxItem 的默认 ControlTemplates 以及我的自定义 (Item-)DataTemplate,但不要使用任何 Code-Behind,或者至少不要太多。也许附加的行为也可以。但我几乎可以肯定,必须有一种方法可以让它在没有 TemplateBinding 或 RelativeSource-stuff 的情况下工作......当然,该解决方案必须让我的键盘选择和文本完成工作,s.th。当列表包含 Hans Josef 和 Hans Peter 时,输入“Hans”应该自动建议 Hans Josef,而快速输入“Hans P”应该自动建议 Hans Peter。

有什么解决办法吗?

4

2 回答 2

9

简短的回答:您想做的事情不能直接在 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); } }
}

<ComboBox TextSearch.TextPath="FullName" ItemsSource="collectionOfPersons"/>

或者,如果您不想接触 Person,您可以创建一个封装类来公开这些属性。

于 2009-11-17T07:33:58.390 回答
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>
于 2009-11-12T17:12:04.903 回答