WPF的数据绑定系统自动生成列表项对象,为单个项应用所需的样式不是很容易。解决方案是ItemContainerStyle 属性。如果设置了ItemContainerStyle 属性,当创建列表项时,列表控件会将其向下传递给每个项。对于ListBox控件,每个项有ListBoxItem 对象表示,对于CombBox 控件,则对应是 CombBoxItem。
交替条目样式
WPF通过两个属性为交替项提供内置支持:AlternationCount 和 AlternationIndex。
-
-
-
-
-
"myGrid"> -
-
-
-
-
-
-
-
"100"/> -
-
"0" Grid.Column="0" ItemContainerStyle="{StaticResource listBoxItemStyle}" ItemsSource="{Binding Path=Orders}" AlternationCount="2" DisplayMemberPath="Price"/> -
也可以直接将样式设置到ListBox层次
-
-
-
-
-
-
-
"myGrid"> -
-
-
-
-
-
-
-
"100"/> -
-
"1" Grid.Column="0" Style="{StaticResource checkBoxListStyle}" ItemsSource="{Binding Path=Orders}" DisplayMemberPath="Price" Name="checkButtonListBox"/> -
样式选择器
可以使用样式选择器来为不同的子项提供不同的样式,自定义样式选择器需要继承自 StyleSelector 类,需要重写 SelectStyle() 方法。
- public class SingleCriteriaHighlightStyleSelector : StyleSelector
- {
- public Style DefaultStyle { get; set; }
- public Style HighlightStyle { get; set; }
- public string PropertyToEvaluate { get; set; }
- public string PropertyValueToHighlight { get; set; }
- public override Style SelectStyle(object item, DependencyObject container)
- {
- Order order = (Order)item;
- if (order.Price > 1000)
- {
- return HighlightStyle;
- }
- else
- {
- return DefaultStyle;
- }
- }
- }
完整的代码文件:
MainWindow.xaml
"ListBoxStyle.MainWindow" - xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:local="clr-namespace:ListBoxStyle"
- mc:Ignorable="d"
- Title="MainWindow" Height="450" Width="800">
-
-
-
-
-
-
-
-
-
-
-
-
"myGrid"> -
-
-
-
-
-
-
-
"100"/> -
-
"0" Grid.Column="0" ItemContainerStyle="{StaticResource listBoxItemStyle}" ItemsSource="{Binding Path=Orders}" AlternationCount="3" DisplayMemberPath="Price"/> -
"0" Grid.Column="1" ItemContainerStyle="{StaticResource radioButtonListStyle}" ItemsSource="{Binding Path=Orders}" DisplayMemberPath="Price" Name="radioButtonListBox"/> -
-
"1" Grid.Column="0" Style="{StaticResource checkBoxListStyle}" ItemsSource="{Binding Path=Orders}" DisplayMemberPath="Price" Name="checkButtonListBox"/> -
"1" Grid.Column="1" ItemsSource="{Binding Path=Orders}" DisplayMemberPath="Price" Name="styleSelectorListBox"> -
-
"{StaticResource DefaultStyle}" HighlightStyle="{StaticResource HighlightStyle}"> -
-
-
-
-
-
MainWindow.xaml.cs
- using System;
- using System.Collections.Generic;
- using System.Collections.ObjectModel;
- using System.ComponentModel;
- using System.Linq;
- using System.Reflection;
- using System.Runtime.CompilerServices;
- using System.Text;
- using System.Threading.Tasks;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Data;
- using System.Windows.Documents;
- using System.Windows.Input;
- using System.Windows.Media;
- using System.Windows.Media.Imaging;
- using System.Windows.Navigation;
- using System.Windows.Shapes;
-
- namespace ListBoxStyle;
-
- public class ViewModelBase : INotifyPropertyChanged
- {
- public event PropertyChangedEventHandler? PropertyChanged;
- protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
- {
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
- }
- protected virtual bool SetProperty<T>(ref T member, T value, [CallerMemberName] string? propertyName = null)
- {
- if (EqualityComparer
.Default.Equals(member, value)) - {
- return false;
- }
- member = value;
- OnPropertyChanged(propertyName);
- return true;
- }
- }
- public class Order : ViewModelBase
- {
- public decimal price = 0;
- public decimal Price { get => price; set => SetProperty(ref price, value); }
- public int volume = 0;
- public int Volume { get => volume; set => SetProperty(ref volume, value); }
-
- public DateTime orderDate = DateTime.Now;
- public DateTime OrderDate { get => orderDate; set => SetProperty(ref orderDate, value); }
-
- public string image = string.Empty;
- public string Image { get => image; set => SetProperty(ref image, value); }
- }
-
- public class SingleCriteriaHighlightStyleSelector : StyleSelector
- {
- public Style DefaultStyle { get; set; }
- public Style HighlightStyle { get; set; }
- public string PropertyToEvaluate { get; set; }
- public string PropertyValueToHighlight { get; set; }
- public override Style SelectStyle(object item, DependencyObject container)
- {
- Order order = (Order)item;
- if (order.Price > 1000)
- {
- return HighlightStyle;
- }
- else
- {
- return DefaultStyle;
- }
- }
- }
-
-
-
- public partial class MainWindow : Window
- {
- public MainWindow()
- {
- InitializeComponent();
- myGrid.DataContext = this;
-
- Order order1 = new Order();
- Order order2 = new Order();
- Order order3 = new Order();
- Order order4 = new Order();
-
- order1.Price = 100;
- order1.Volume = 10;
-
- order2.Price = 1000;
- order2.Volume = 100;
-
- order3.Price = 10000;
- order3.Volume = 1000;
-
- order4.Price = 100000;
- order4.Volume = 10000;
-
- Orders.Add(order1);
- Orders.Add(order2);
- Orders.Add(order3);
- Orders.Add(order4);
- }
-
- public ObservableCollection
Orders {get; set;} = new (); -
- private void Button_Click(object sender, RoutedEventArgs e)
- {
- string message = "";
- if(radioButtonListBox.SelectedItem != null)
- {
- Order order = (Order)radioButtonListBox.SelectedItem;
- message = order.Price.ToString();
- }
- message += "\n";
- foreach (var selectedItem in checkButtonListBox.SelectedItems)
- {
- Order order = (Order)selectedItem;
- message += order.Price.ToString() + " ";
- }
- MessageBox.Show(message);
- }
-
- private void Button_Click_1(object sender, RoutedEventArgs e)
- {
- Orders[1].Price = 50000;
- StyleSelector selector = styleSelectorListBox.ItemContainerStyleSelector;
- styleSelectorListBox.ItemContainerStyleSelector = null;
- styleSelectorListBox.ItemContainerStyleSelector = selector;
-
- }
- }