【问题标题】:Cannot change the style of the selected item in a ListBox无法更改列表框中所选项目的样式
【发布时间】:2012-09-12 09:48:18
【问题描述】:

我正在尝试更改列表框的焦点/选定项。我的申请基于this article。 目前我正在尝试通过数据模板设置 ListBoxItem 样式:

    <DataTemplate x:Key="ItemTemplate">
        <TextBlock Text="{Binding}" 
                   Foreground="Black" 
                   FontFamily="Segoe UI" 
                   FontSize="22"
                   HorizontalAlignment="Left"
                   Padding="15,10,0,0"
                   />
    </DataTemplate>

    <DataTemplate x:Key="SelectedTemplate">
        <TextBlock Text="{Binding}" 
                   Foreground="Red" 
                   FontFamily="Segoe UI" 
                   FontSize="30"
                   HorizontalAlignment="Left"
                   Padding="15,10,0,0"
                   />
    </DataTemplate>

我的想法是使用触发器在这些模板之间切换:

<Style TargetType="{x:Type ListBoxItem}" x:Key="ContainerStyle">
        <Setter Property="ContentTemplate" Value="{StaticResource ItemTemplate}" />
        <Style.Triggers>
            <Trigger Property="IsSelected" Value="True">
                <Setter Property="ContentTemplate" Value="{StaticResource SelectedTemplate}" />
            </Trigger>
        </Style.Triggers>
    </Style>

列表框如下所示:

<ListBox x:Name="valuesItemsCtrl" 
         BorderThickness="0" 
         ItemContainerStyle="{StaticResource ContainerStyle}"
         Background="Transparent"
         Tag="{Binding }">
    <ListBox.AlternationCount>
        <Binding>
            <Binding.Path>Values.Count</Binding.Path>
        </Binding>
    </ListBox.AlternationCount>
        <ListBox.ItemsSource>
            <Binding>
                <Binding.Path>Values</Binding.Path>
            </Binding>
        </ListBox.ItemsSource>
        <ListBox.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel />
            </ItemsPanelTemplate>
        </ListBox.ItemsPanel>
    </ListBox>

最后我将模板添加到另一个 ListBox:

<ListBox x:Name="tumblersCtrl" 
                 BorderThickness="0" 
                 Background="Transparent" 
                 ItemsSource="{Binding Tumblers, ElementName=thisCtrl}" 
                 ItemTemplate="{StaticResource TumblerTemplate}">
</ListBox>

感谢任何帮助或提示!

【问题讨论】:

    标签: c# wpf listbox


    【解决方案1】:

    使用ItemTemplate 和数据触发器:

    <ListBox ItemsSource="{Binding}">
        <ListBox.ItemContainerStyle>
            <Style TargetType="{x:Type ListBoxItem}">
                <Setter Property="IsSelected" Value="{Binding IsSelected}"/>
            </Style>
        </ListBox.ItemContainerStyle>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Name}" 
                           Foreground="Black" 
                           FontFamily="Segoe UI" 
                           FontSize="22" 
                           HorizontalAlignment="Left" 
                           Padding="15,10,0,0"
                           x:Name="tbName"/>
                <DataTemplate.Triggers>
                    <DataTrigger Binding="{Binding IsSelected}" Value="True">
                        <Setter TargetName="tbName" Property="Foreground" Value="Red"/>
                        <Setter TargetName="tbName" Property="FontSize" Value="30"/>
                    </DataTrigger>
                </DataTemplate.Triggers>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>
    

    绑定数据是以下各项的集合:

    public class ViewModel : ViewModelBase
    {
        public String Name
        {
            get { return name; }
            set
            {
                if (name != value)
                {
                    name = value;
                    OnPropertyChanged("Name");
                }
            }
        }
        private String name;
    
        public Boolean IsSelected
        {
            get { return isSelected; }
            set
            {
                if (isSelected != value)
                {
                    isSelected = value;
                    OnPropertyChanged("IsSelected");
                }
            }
        }
        private Boolean isSelected;
    }
    

    窗口代码隐藏:

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new[]
            {
                new ViewModel { Name = "John", IsSelected = true },
                new ViewModel { Name = "Mary" },
                new ViewModel { Name = "Pater" },
                new ViewModel { Name = "Jane" },
                new ViewModel { Name = "James" },
            };
        }
    }
    

    【讨论】:

    • 我不知道你想让我选择哪个类而不是 ViewModel 和 ViewModelBase
    • @SeveFriede: ViewModel 是一个单独的类,在单独的代码文件中。您的意思是为ListBox 分配数据上下文吗?如果是这样,我会更新答案。
    • @SeveFriede: ViewModelBaseINotifyPropertyChanged 接口的简单实现。 ViewModel 是一个示例模型,代表项目控制的数据项(您要显示的东西)(在您的情况下为 ListBox)。
    • 我花了一些时间来理解数据触发和绑定......但最终就是这样!非常感谢! :)
    【解决方案2】:

    如果您想更改模板,请使用DataTemplateSelector

    关闭您的 ContainerStyle,而是将 ListBox.ItemsTemplateSelector 设置为您的自定义数据模板选择器作为静态资源。

    您可以在link 中找到详细示例。

    编辑: 根据您的评论,您不需要 DataTemplate 只需在触发器中设置这两个属性:

    <Style TargetType="{x:Type ListBoxItem}" x:Key="ContainerStyle">
        <Setter Property="Foreground" Value="Black" />
        <Setter Property="FontSize" Value="22" />
        <Setter Property="FontFamily" Value="Segoe UI" />
        <Setter Property="HorizontalAlignment" Value="Left" />
        <Setter Property="Padding" Value="15,10,0,0" />
        <Style.Triggers>
            <Trigger Property="IsSelected" Value="True">
                <Setter Property="Foreground" Value="Red" />
                <Setter Property="FontSize" Value="30" />
            </Trigger>
        </Style.Triggers>
    </Style>
    

    【讨论】:

    • 我想要做的就是改变 TextColor 和 FontSize。我真的需要一个 DataTemplateSelector 吗?我认为我的问题是实际上没有 selectionChanged 事件:S
    猜你喜欢
    • 2012-10-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-01
    • 2013-05-03
    • 1970-01-01
    相关资源
    最近更新 更多