【问题标题】:WPF ListBox selection issues, providing feedback to userWPF ListBox 选择问题,向用户提供反馈
【发布时间】:2013-01-20 19:14:22
【问题描述】:

我正在尝试为具有一个画布但多个“页面”的应用创建一个显示页面内容缩略图视图的列表框。是的,这可能不是最好的起点,但出于历史原因,这就是我所拥有的。 我已经实现了 ListBox,其数据绑定到具有 PageData 的 ObservableCollection 的单例“工作簿”(页面上出现的所有内容,包括它的背景)。 我真正真正想要的是能够在 ListBoxItem 被选中时更改它的边框颜色,并在它的内容是托管集合的类中当前选定的项目时保持该边框颜色。

我的问题是:- 1/我无法让ListBox在程序启动时选择第一项。

2/ 当 ListBox 失去焦点时,SelectedIndex 总是 -1(所以没有选择)

3/ 添加到 ListBox 导致没有选择 (SelectedIndex == -1)

4/ 使用触发器,我可以设置 selectedItem 的边框,但是当 ListBox 失去焦点时这会丢失。由于 ListBoxItem 显示的图像是不透明的,因此在失焦时使选择颜色保持不变的“标准”方式不起作用 - 即

<Style x:Key="PsThumb">
                <Style.Resources>
                    <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="White"></SolidColorBrush>
                    <SolidColorBrush x:Key="{x:Static SystemColors.ControlBrushKey}" Color="White"></SolidColorBrush>
                </Style.Resources>
</Style>

我的 ListBox 代码如下:-

<ListBox  x:Name="PageSorter" Style="{StaticResource PsThumb}"  Width="148" BorderThickness="4" HorizontalContentAlignment="Stretch" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
        VerticalAlignment="Stretch" ItemsSource="{Binding Pages,Source={StaticResource WorkBook}}" SelectedItem="{Binding Path=CurrentPageData, Mode=TwoWay}" 
         AllowDrop="True" ScrollViewer.VerticalScrollBarVisibility="Auto">
                <ListBox.ItemTemplate>
                <DataTemplate>
                    <Grid>
                         <Border x:Name="border" BorderBrush="DarkGray" BorderThickness="4" Margin="2,4,2,4" CornerRadius="5">
                             <Border.Effect>
                                 <DropShadowEffect ShadowDepth="6"/>
                             </Border.Effect>
                             <Image Source="{Binding Thumbnail}" Width="130" Height="95" Stretch="Fill"/>
                         </Border>
                    </Grid>
                        <DataTemplate.Triggers>
                            <DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}},Path=IsSelected}" Value="True">
                                <Setter TargetName="border" Property="BorderBrush" Value="Red"></Setter>
                            </DataTrigger>
                        </DataTemplate.Triggers>
                    </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>

【问题讨论】:

  • 我无法显示代码,不允许在评论中添加它:(

标签: wpf listbox selection


【解决方案1】:

实现您所要求的最简单方法是将DataTrigger 绑定到ListBox 的项目内的属性。在下面的示例中,我在 Contact 类中添加了 Selected 属性:

public class Contact : INPCBase
{
    public string Name { get; set; }

    private bool _Selected;
    public bool Selected 
    {
        get { return _Selected; }
        set
        {
            _Selected = value;
            NotifyPropertyChanged("Selected");
        }
    }
}

然后我将我的ListBox 绑定到List&lt;Contact&gt;。当用户检查CheckBox时,我们更改Selected属性,进而触发Style:

<Window x:Class="WpfApp.ListboxKeepSelectionWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="ListboxKeepSelectionWindow" Height="277" Width="343"
    xmlns:me="clr-namespace:WpfApp">

<Window.Resources>
    <me:ContactList x:Key="sample"/>

    <Style TargetType="ListBoxItem" x:Key="SelectedListBoxItemStyle">
        <Style.Triggers>
            <DataTrigger Binding="{Binding Path=Selected}" Value="True">
                <Setter Property="BorderBrush" Value="Orange"/>
            </DataTrigger>
        </Style.Triggers>
    </Style>
</Window.Resources>

<Grid>
    <ListBox Name="lbxContacts"
             ItemsSource="{StaticResource ResourceKey=sample}"
             SelectionMode="Extended"
             ItemContainerStyle="{StaticResource ResourceKey=SelectedListBoxItemStyle}" 
             SelectionChanged="lbxContacts_SelectionChanged">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel>
                    <CheckBox IsChecked="{Binding Path=Selected}">
                        <TextBlock Text="{Binding Path=Name}"/>
                    </CheckBox>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
</Grid>

为了允许用户在不使用复选框的情况下选择项目,我在ListBox 上添加了这个小事件。由于Contact 类实现了INotifyPropertyChanged 接口,CheckBox 的值已更新,因此用户知道选择有效:

    private void lbxContacts_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        foreach (Contact c in e.AddedItems)
        {
            c.Selected = !c.Selected;
        }
    }

当您想要获取选定项目的列表时,您只需对 ItemsSource 使用 LINQ 查询即可获取 Selected == true 所在的项目。

【讨论】:

  • 设置 ItemContainerStyle 无效 - 但更改 DataTemplate 触发器有效!我使用 Binding Path=Selected 而不是 Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBoxItem}},Path=IsSelected}" 非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多