【问题标题】:Set TextSearch.Text for WPF-ComboBoxItem via DataTemplate通过 DataTemplate 为 WPF-ComboBoxItem 设置 TextSearch.Text
【发布时间】:2010-11-09 18:32:15
【问题描述】:

我使用数据模板来可视化组合框中的一些项目, 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。

有什么解决办法吗?

【问题讨论】:

  • 至少到现在我还是很有信心的,这个任务确实不太容易。或者长篇大论只是让人惊慌失措……
  • 我快要放弃了。我设法通过在 ComboBox.ItemContainerStyle 中设置 ComboBoxItem 来携带正确的 TextSearch.Text-Property(而不是 ItemTemplate,就像我之前所做的那样)。现在它在可视化树中看起来相当不错(又是 Snoop),但不幸的是它没有任何效果。输入“Hans”或其他内容后没有选择。

标签: c# wpf data-binding combobox datatemplate


【解决方案1】:

简短回答:您想做的事情不能直接在 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,您可以创建一个封装类来公开这些属性。

【讨论】:

  • 恐怕你是对的。到目前为止,如果不向类添加额外的属性,甚至是包装和扩展旧类的新类,就没有可行的解决方案。正如问题表明这些可能性是已知的但不想要,我不能将其标记为 the 答案 - 除非您通过一些证据或解释扩展您的简短答案,为什么这是不可能的。
【解决方案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>

【讨论】:

  • 听起来很合理,但不幸的是没有奏效。键盘选择的行为不如预期,可能输入仍然与人员的 ToString 值进行比较, textsearch.text 根本没有效果。我想绑定确实有效,但 ComboBox 忽略了它。
  • 不适合我,你不能从样式中定位这个 TextSearch.Text
猜你喜欢
  • 2012-04-26
  • 2011-03-08
  • 2011-04-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-30
  • 2021-12-03
  • 1970-01-01
相关资源
最近更新 更多