调整WPF ListBox选择框的大小

时间:2012-06-16 14:07:05

标签: c# wpf listbox styles datatemplate

对于一个项目,我实现了一个像控件这样的小型IntelliSense,它不是ListBox。其DataTemplateStackPanelImage和一个TextBlock组成。没有其他的。正如您在我的控件的第一个屏幕截图中所看到的,ListBox的选择框选择整个项目(通常正是人们期望的那样):

Custom ListBox

然而,VS11的“被盗”图标质量很差,所以我想像Visual Studio一样调整选择:

Visual Studio IntelliSense

您可以看到只选择了文本(可视化表示确实忽略了图像/图标),我也想知道如何实现这种行为。

编辑:图标只是具有透明背景的GIF文件。我会用更好的替换它们,但尽管如此我仍然非常关注如何获得理想的行为。

2 个答案:

答案 0 :(得分:3)

这是一个替换ListBoxItem控件模板的解决方案。在我的测试中,我只显示两个文本字符串,第二个突出显示。

<Page.Resources>
    <Style x:Key="ItemStyle" TargetType="ListBoxItem">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="ListBoxItem">
                    <ContentPresenter/>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

    <Style x:Key="Selected" TargetType="{x:Type TextBlock}">
        <Style.Triggers>
            <DataTrigger Binding="{Binding Path=IsSelected, 
                         RelativeSource={RelativeSource Mode=FindAncestor, 
                         AncestorType={x:Type ListBoxItem}}}" Value="True">
                <Setter Property="Background" 
                        Value="{x:Static SystemColors.HighlightBrush}"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>

    <DataTemplate x:Key="ItemTemplate" DataType="{x:Type ViewModel:DataItem}">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="auto" SharedSizeGroup="c1"/>
                <ColumnDefinition Width="auto" SharedSizeGroup="c2"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Image Source="../Images/Collapse.png"/>
            <TextBlock Grid.Column="1" Text="{Binding Name}" Margin="0,0,5,0"/>
            <TextBlock Style="{StaticResource Selected}" 
                       Grid.Column="2" Text="{Binding Description}"/>
        </Grid>
    </DataTemplate>
</Page.Resources>

<Page.DataContext>
    <Samples:Page3ViewModel/>
</Page.DataContext>

<Grid>
    <ListBox 
        Grid.IsSharedSizeScope="True"
        SelectedIndex="2"
        HorizontalContentAlignment="Stretch"
        ItemsSource="{Binding Items}" 
        ItemContainerStyle="{StaticResource ItemStyle}"
        ItemTemplate="{StaticResource ItemTemplate}"/>
</Grid>

视图模型包含一组简单数据项

public class Page3ViewModel
{
    public Page3ViewModel()
    {
        Items = new List<DataItem>
            {
                new DataItem{Name = "One", Description = "First"},
                new DataItem{Name = "Two", Description = "Second"},
                new DataItem{Name = "Three", Description = "Third"},
                new DataItem{Name = "Four", Description = "Fourth"},
            };
    }
    public IEnumerable<DataItem> Items { get; private set; }
}

给予

enter image description here

答案 1 :(得分:1)

您的问题是由于WPF呈现 ListBox 中的每个项目的方式。它使用 ItemContainerStyle 包装 ListBoxItem 中的每个项目。这个 ListBoxItem 包含要显示的内容(在您的情况下是包含Image和TextBlock的StackPanel)。

默认情况下, ListBoxItem 会在其显示的所有内容周围显示蓝色矩形。

我想出了一个解决方案,但这是一个黑客攻击。只需将图像放大,使背景像素颜色与列表框(在我的情况下为白色)的背景颜色相匹配,然后使用以下XAML。

<ListBox Margin="5"
         ItemsSource="{Binding Items}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal"
                        Margin="-2,0,0,0">
                <Image Source="Save-icon.png" />
                <TextBlock Margin="5,8,0,0"
                           Text="{Binding}" />
            </StackPanel>
        </DataTemplate>
     </ListBox.ItemTemplate>
</ListBox>

结果如下:

enter image description here

<强>更新

我已经想出了一个修改,这使得它不再是一个黑客攻击。 在我的 ItemTemplate 中,我用 Border 包围了图像,它使用绑定从其父 ListBox 中获取其背景颜色。 (图像周围不再有边框)。

将XAML更新为:

<ListBox Margin="5"
         ItemsSource="{Binding Items}"
         Background="LightSteelBlue">

    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal"
                        Margin="-2,0,0,0">
                <Border Background="{Binding Path=Background, RelativeSource={RelativeSource AncestorType=ListBox}}"
                        Padding="10">
                    <Image Source="Save-icon.png"/>
                 </Border>
                 <TextBlock Margin="5,8,0,0"
                            Text="{Binding}" />
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>

</ListBox>

这是新结果:

enter image description here

现在您需要做的就是更新 ListBox 的背景颜色,一切都会自动调整。 E.G。

<ListBox Margin="20"
         ItemsSource="{Binding Items}"
         Background="PeachPuff">

enter image description here