WPF 自定义ListBox
需求:ListBox只在选中时有相应的高亮颜色,光标悬浮或滑动时不显示高亮;以满足在触屏上时不会误导人操作……
同时为了应避免所添加的item在触屏上偶尔出现点击不响应,以提高可用性。
以下为实现代码:
namespace FrameControlLibrary { /// <summary> /// 按照步骤 1a 或 1b 操作,然后执行步骤 2 以在 XAML 文件中使用此自定义控件。 /// /// 步骤 1a) 在当前项目中存在的 XAML 文件中使用该自定义控件。 /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根 /// 元素中: /// /// xmlns:MyNamespace="clr-namespace:FrameControlLibrary" /// /// /// 步骤 1b) 在其他项目中存在的 XAML 文件中使用该自定义控件。 /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根 /// 元素中: /// /// xmlns:MyNamespace="clr-namespace:FrameControlLibrary;assembly=FrameControlLibrary" /// /// 您还需要添加一个从 XAML 文件所在的项目到此项目的项目引用, /// 并重新生成以避免编译错误: /// /// 在解决方案资源管理器中右击目标项目,然后依次单击 /// “添加引用”->“项目”->[浏览查找并选择此项目] /// /// /// 步骤 2) /// 继续操作并在 XAML 文件中使用控件。 /// /// <MyNamespace:JListBox/> /// /// </summary> public class JListBox : ListBox { /* static JListBox() { DefaultStyleKeyProperty.OverrideMetadata(typeof(JListBox), new FrameworkPropertyMetadata(typeof(JListBox))); }*/ public JListBox() { this.Background = Brushes.Transparent; this.Loaded += JListBox_Loaded; //this.SelectionChanged += JListBox_SelectionChanged; } static bool isFirst = true;//只在首次加载时,禁止触控笔事件 private void JListBox_Loaded(object sender, RoutedEventArgs e) { if (isFirst) { isFirst = false; this.ItemContainerStyle = new CustomListBoxStyle(); foreach (ListBoxItem item in this.Items) { StylusFalse.StylusEnable(item); } } } private void JListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { //((ListBoxItem)this.SelectedItem).FocusVisualStyle = (Style)Application.Current.FindResource(SystemParameters.FocusVisualStyleKey); // Color color = (Color)ColorConverter.ConvertFromString("#BEE6FD"); //((ListBoxItem)this.SelectedItem).Background = SystemColors.HighlightBrush;//new SolidColorBrush(color); } } public class CustomListBoxStyle : Style { public CustomListBoxStyle() { TargetType = typeof(ListBoxItem); Setter templateSetter = new Setter() { Property = ListBoxItem.TemplateProperty }; ControlTemplate template = new ControlTemplate(typeof(ListBoxItem)); FrameworkElementFactory borderFactory = new FrameworkElementFactory(typeof(Border)); borderFactory.SetValue(Border.BackgroundProperty, new TemplateBindingExtension(ListBoxItem.BackgroundProperty)); borderFactory.SetValue(Border.BorderThicknessProperty, new Thickness(1)); FrameworkElementFactory contentPresenterFactory = new FrameworkElementFactory(typeof(ContentPresenter)); contentPresenterFactory.SetValue(ContentPresenter.HorizontalAlignmentProperty, HorizontalAlignment.Center); contentPresenterFactory.SetValue(ContentPresenter.VerticalAlignmentProperty, VerticalAlignment.Center); borderFactory.AppendChild(contentPresenterFactory); template.VisualTree = borderFactory; templateSetter.Value = template; Setters.Add(templateSetter); //选中颜色 Setter backgroundSetter = new Setter(); backgroundSetter.Property = ListBoxItem.BackgroundProperty; backgroundSetter.Value = Brushes.Transparent; DataTrigger selectedTrigger = new DataTrigger(); selectedTrigger.Binding = new Binding("IsSelected") { RelativeSource = new RelativeSource(RelativeSourceMode.Self) }; selectedTrigger.Value = true; selectedTrigger.Setters.Add(new Setter(ListBoxItem.BackgroundProperty, new SolidColorBrush(Color.FromArgb(0xFF, 0xBE, 0xE6, 0xFD)))); Triggers.Add(selectedTrigger); Setters.Add(backgroundSetter); } } }
禁用触控笔事件
internal class StylusFalse { public static void StylusEnable<T>(T obj) where T : Control { Stylus.SetIsFlicksEnabled(obj, false); Stylus.SetIsPressAndHoldEnabled(obj, false); Stylus.SetIsTapFeedbackEnabled(obj, false); Stylus.SetIsTouchFeedbackEnabled(obj, false); } }
注:开始时实现选中item背景色改变是利用的SelectionChanged事件来改变,但是改变后会造成这个item的背景总是高亮,即取消选中后它还是高亮。于是后续将xaml中实现选中高亮的代码改为了后台代码,以实现这一目的。后续有更好办法,再次改进……
以下为在page或window中实现listbox仅选中item高亮的代码:
<Style TargetType="{x:Type ListBoxItem}"> <Setter Property="Background" Value="Transparent"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type ListBoxItem}"> <Border Background="{TemplateBinding Background}" BorderThickness="1"> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/> </Border> </ControlTemplate> </Setter.Value> </Setter> <Style.Triggers> <!--<Trigger Property="IsSelected" Value="True"> <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.HighlightColor}}"/> </Trigger>--> <DataTrigger Binding="{Binding IsSelected, RelativeSource={RelativeSource Self}}" Value="true"> <Setter Property="Background" Value="#BEE6FD"/> </DataTrigger> </Style.Triggers> </Style>
*****有道无术,术尚可求;有术无道,止于术。*****