如何在Silverlight的组合框中为选定和下拉状态使用不同的模板?

时间:2008-11-07 09:00:48

标签: .net wpf silverlight xaml combobox

我似乎无法为ComboBoxItem设置ContentTemplate。我试图这样做的原因是我希望在组合框中有2次出现我的数据。当组合框打开(菜单关闭)时,我想要一个文本框(带有图像名称)和它下面的图像控件。当我选择项目时,我希望组合框只显示一个带有图像名称的文本框。

我想我可以通过修改ComboBox的ItemTemplate和ItemContainerStyle来实现这一点。 ItemContainerStyle包含以下ContentPresenter:

<ContentPresenter HorizontalAlignment="Left" Margin="{TemplateBinding Padding}" x:Name="contentPresenter" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}"/>

所以我假设我可以在这里设置ContentTemplate,它会起作用。但我似乎无法让它发挥作用:

<DataTemplate x:Key="ComboBoxDataTemplate">
            <Grid>
                <TextBlock Text="{Binding Path='Name'}"/>
            </Grid>
        </DataTemplate>

<DataTemplate x:Key="ComboBoxItemTemplate">
            <StackPanel>
                <TextBlock Text="{Binding Path='Name'}"/>
                <Image Source="{Binding Path='Source'}" Width="64" Height="64"/>
            </StackPanel>
        </DataTemplate>

        <Style x:Key="ComboBoxItemStyle1" TargetType="ComboBoxItem">
...
            <Setter Property="ContentTemplate" Value="{StaticResource ComboBoxItemTemplate}"/>

...

这是我的组合框:

<ComboBox Width="70" Margin="3,0,0,0"
                        ItemsSource="{StaticResource Source}"
                        ItemTemplate="{StaticResource ComboBoxDataTemplate}"
                        ItemContainerStyle="{StaticResource ComboBoxItemStyle1}"
                        />

我能让它工作的唯一方法是从ItemContainerStyle中删除ContentPresenter,并将其替换为我的自定义模板(ComboBoxItemTemplate)的内容。但我不认为我应该使用这种方法,因为它意味着ContentPresenter不再存在(ComboBox中的代码可能依赖于它)。

有关显示具有不同下拉菜单和所选模板的组合框的任何帮助都将非常感谢!

3 个答案:

答案 0 :(得分:5)

ComboBox.ItemTemplate只是设置ComboBoxItem.ContentTemplate的便捷方式。所以上面的代码基本上试图将ComboBoxItem.ContentTemplate设置两次。

正如Jobi指出的那样,您可以尝试仅使用自定义样式。如果您始终知道内容的类型,则可以安全地排除ContentPresenter。 ContentPresenter只允许您使用DataTemplate显示一些随机数据。但你可以用TextBlock和Image替换它。你只是失去了指定DataTemplate的能力。

Jobi方法的问题在于选择项目不会显示它的图像,即使它在下拉列表中也是如此。实际上,所选项目显示在两个位置(ComboBox的下拉列表和主体)。在一个位置,您需要一个DataTemplate,而在另一个位置需要另一个DataTemplate。

你最好的选择是重新组合ComboBox。您可以从here获取默认样式。有一个名为“ContentPresenter”的ContentPresenter。你需要:

  1. 删除/更改ContentPresenter的名称,因此ComboBox不会自动设置Content / ContentTemplate属性
  2. 绑定ContentPresenter.Content属性,如下所示:“{TemplateBinding SelectedObject}”
  3. 将ContentPresenter.ContentTemplate属性设置为不带Image的DataTemplate
  4. 将ComboBox.ItemTemplate属性设置为带有Image和TextBlock的DataTemplate,就像
  5. 一样
  6. 为ComboBox样式指定一个显式键,如x:Key =“MyComboBoxStyle”
  7. 使用ComboBox上的样式,如Style =“{StaticResource MyComboBoxStyle}”
  8. 当在ComboBox的主体中显示所选项时,这会有效地忽略ComboBoxItem.ContentTemplate,但在下拉列表中显示ComboBoxItem时会使用它。

答案 1 :(得分:0)

您只需使用ItemsContainerStyle即可实现此目的。添加TextBlock和Image而不是ContentPresenter。添加VisualStateManager并根据VSM的Selected状态切换Image控件的Visibility。

答案 2 :(得分:0)

DataTemplate主要用于数据可视化,最好在ControlTemplate(控制行为)中提供所有与UI相关的动态。如果您没有ContentPresenter,则没有潜在的问题。唯一的问题是,如果您想从其他ComboBox重用此ControlTemplate。然后你可以在那里用ContentPresenter声明另一个干净的Control模板。