WPF ListView与ListBox(选中)项样式

WPF ListView与ListBox(选中)项自定义样式

想用ListBox或者ListView控件,做一个菜单栏等,却发现很难改变ListBoxItem/ListViewItem项在鼠标移过、选中的默认蓝色背景与边框。

首先尝试使用控件的Style来设置ItemTemplate上的Triggers,结果时不成功。

经过查资料发现很少,最后在自定义List项时,发现对ListBoxItem/ListViewItem进行样式设计可以改变项的样式。具体实现如下所示。

ListViewItem

废话不说,我们首先上代码。

1.在资源模块中定义好我们的Item样式

					<Style x:Key="FocusVisual">
                        <Setter Property="Control.Template">
                            <Setter.Value>
                                <ControlTemplate>
                                    <Rectangle Margin="0" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="0" StrokeDashArray="1 2"/>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>
                    <!-- Item项相关颜色 -->
                    <SolidColorBrush x:Key="Item.MouseOver.Background" Color="#DADADA"/>
                    <SolidColorBrush x:Key="Item.MouseOver.Border" Color="#3DDADADA"/>
                    <SolidColorBrush x:Key="Item.SelectedInactive.Background" Color="#FF0B7AFF"/>
                    <SolidColorBrush x:Key="Item.SelectedInactive.Border" Color="#3DDADADA"/>
                    <SolidColorBrush x:Key="Item.SelectedInactive.Foreground" Color="#FFFFFFFF"/>
                    <SolidColorBrush x:Key="Item.SelectedActive.Background" Color="#FF0B7AFF"/>
                    <SolidColorBrush x:Key="Item.SelectedActive.Border" Color="#FF0B7AFF"/>
                    <SolidColorBrush x:Key="Item.SelectedActive.Foreground" Color="#FFFFFFFF"/>

                    <!-- Item项样式 -->
                    <Style TargetType="{x:Type ListViewItem}">
                        <Setter Property="HorizontalContentAlignment" Value="Center"/>

                        <Setter Property="SnapsToDevicePixels" Value="True"/>
                        <Setter Property="Padding" Value="4,1"/>
                        <Setter Property="Background" Value="Transparent"/>
                        <Setter Property="Foreground" Value="Black"/>
                        <Setter Property="BorderBrush" Value="Transparent"/>
                        <Setter Property="BorderThickness" Value="0"/>
                        <Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="{x:Type ListBoxItem}">
                                    <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
                                        <ContentControl x:Name="Ct" Foreground="{TemplateBinding Foreground}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
                                            <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                                        </ContentControl>
                                    </Border>
                                    <ControlTemplate.Triggers>
                                        <MultiTrigger>
                                            <MultiTrigger.Conditions>
                                                <Condition Property="IsMouseOver" Value="True"/>
                                            </MultiTrigger.Conditions>
                                            <Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.MouseOver.Background}"/>
                                            <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.MouseOver.Border}"/>
                                        </MultiTrigger>
                                        <MultiTrigger>
                                            <MultiTrigger.Conditions>
                                                <Condition Property="Selector.IsSelectionActive" Value="False"/>
                                                <Condition Property="IsSelected" Value="True"/>
                                            </MultiTrigger.Conditions>
                                            <Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.SelectedInactive.Background}"/>
                                            <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.SelectedInactive.Border}"/>
                                            <Setter Property="Foreground" TargetName="Ct" Value="{StaticResource Item.SelectedInactive.Foreground}"/>
                                        </MultiTrigger>
                                        <MultiTrigger>
                                            <MultiTrigger.Conditions>
                                                <Condition Property="Selector.IsSelectionActive" Value="True"/>
                                                <Condition Property="IsSelected" Value="True"/>
                                            </MultiTrigger.Conditions>
                                            <Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.SelectedActive.Background}"/>
                                            <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.SelectedActive.Border}"/>
                                            <Setter Property="Foreground" TargetName="Ct" Value="{StaticResource Item.SelectedActive.Foreground}"/>
                                        </MultiTrigger>
                                        <Trigger Property="IsEnabled" Value="False">
                                            <Setter Property="TextElement.Foreground" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                                        </Trigger>
                                    </ControlTemplate.Triggers>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>

2.样式应用

    			<ListView Margin="2,5"
                          ItemsSource="{Binding Path=MelphiDataSource,RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}">
                    <ListView.Template>
                        <ControlTemplate TargetType="ListView">
                            <Border CornerRadius="15"
                        BorderThickness="{TemplateBinding BorderThickness}"
                        BorderBrush="{TemplateBinding BorderBrush}">
                                <Border.OpacityMask>
                                    <VisualBrush>
                                        <VisualBrush.Visual>
                                            <Border SnapsToDevicePixels="True"
                                        Background="Black"
                                        CornerRadius="{Binding CornerRadius, RelativeSource={RelativeSource AncestorType=Border}}"
                                        Width="{Binding ActualWidth, RelativeSource={RelativeSource AncestorType=Border}}"
                                        Height="{Binding ActualHeight, RelativeSource={RelativeSource AncestorType=Border}}"/>
                                        </VisualBrush.Visual>
                                    </VisualBrush>
                                </Border.OpacityMask>
                                <ItemsPresenter>

                                </ItemsPresenter>
                            </Border>
                        </ControlTemplate>
                    </ListView.Template>
                    <ListView.ItemsPanel>
                        <ItemsPanelTemplate>
                            <UniformGrid Rows="1"/>
                        </ItemsPanelTemplate>
                    </ListView.ItemsPanel>
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <Grid Background="#01000000">
                                <Grid.ToolTip>
                                    <StackPanel MinWidth="200">
                                        <TextBlock Text="{Binding Name, Mode=OneWay}"
                                                   FontWeight="Bold"/>

                                        <TextBlock Text="{Binding SelectedValue, Mode=OneWay}"/>
                                    </StackPanel>
                                </Grid.ToolTip>

                                <TextBlock Text="{Binding Name}" >
                                    <TextBlock.Style>
                                        <Style TargetType="{x:Type TextBlock}" >
                                            <Setter Property="Margin" Value="0"/>
                                            <Setter Property="HorizontalAlignment" Value="Center"/>
                                            <Setter Property="VerticalAlignment" Value="Center"/>
                                            <Setter Property="Foreground" Value="{Binding Foreground, RelativeSource={RelativeSource FindAncestor, AncestorType=ContentControl}}"/>
                                        </Style>
                                    </TextBlock.Style>
                                </TextBlock>
                            </Grid>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>

3.数据模型定义与绑定

 /// <summary>
    /// ListViewsView.xaml 的交互逻辑
    /// </summary>
    public partial class ListViewsView : UserControl
    {
        public ListViewsView()
        {
            InitializeComponent();

            // 获取数据源
            MelphiDataSource = MelphiDataService.GetDataSource();
        }

        private ObservableCollection<MelphiDataItem> melphiDataSource = new ObservableCollection<MelphiDataItem>();

        /// <summary>
        /// 数据源
        /// </summary>
        public ObservableCollection<MelphiDataItem> MelphiDataSource
        {
            get
            {
                return melphiDataSource;
            }
            set
            {
                melphiDataSource = value;
            }
        }
    }

    /// <summary>
    /// 数据服务
    /// </summary>
    public class MelphiDataService
    {
        /// <summary>
        /// 模拟获取数据源
        /// </summary>
        /// <returns></returns>
        public static ObservableCollection<MelphiDataItem> GetDataSource()
        {
            ObservableCollection<MelphiDataItem> melphiDatas = new ObservableCollection<MelphiDataItem>();

            melphiDatas.Add(new MelphiDataItem()
            {
                Name = "DataA",
                IsEnabled = true,
                SelectedValue = "Kea",
                SelectionSource = new List<string>() { "Kea", "Lau", "Nuh" }
            });

            melphiDatas.Add(new MelphiDataItem()
            {
                Name = "DataB",
                IsEnabled = true,
                SelectedValue = "Lau",
                SelectionSource = new List<string>() { "Kea", "Lau", "Nuh" }
            });

            melphiDatas.Add(new MelphiDataItem()
            {
                Name = "DataC",
                IsEnabled = true,
                SelectedValue = "invalid",
                SelectionSource = new List<string>() { "invalid", "valid" }
            });

            melphiDatas.Add(new MelphiDataItem()
            {
                Name = "DataD",
                IsEnabled = true,
                SelectedValue = "invalid",
                SelectionSource = new List<string>() { "invalid", "valid" }
            });

            melphiDatas.Add(new MelphiDataItem()
            {
                Name = "DataE",
                IsEnabled = false,
                SelectedValue = "0",
                SelectionSource = new List<string>() { "0", "1", "2", "3", "4", "5", "6" }
            });

            var listsource = new List<string>();
            for (int i = 0; i <= 200; i+=20)
            {
                listsource.Add(i.ToString());
            }

            melphiDatas.Add(new MelphiDataItem()
            {
                Name = "DataF",
                IsEnabled = true,
                SelectedValue = "100",
                SelectionSource = listsource
            });

            melphiDatas.Add(new MelphiDataItem()
            {
                Name = "DataG",
                IsEnabled = true,
                SelectedValue = "3",
                SelectionSource = new List<string>() { "0", "1", "2", "3", "4", "5", "6" }
            });

            return melphiDatas;
        }
    }


    /// <summary>
    /// 数据项
    /// </summary>
    public class MelphiDataItem
    {
        /// <summary>
        /// 数据名称
        /// </summary>
        public string Name { get; set; }

        /// <summary>
        /// 数据标识
        /// </summary>
        public bool IsEnabled { get; set; }

        /// <summary>
        /// 设定值
        /// </summary>
        public string SelectedValue { get; set; }

        /// <summary>
        /// 设定值选定项集合
        /// </summary>
        public List<string> SelectionSource { get; set; }

    }

4.效果

在这里插入图片描述

ListBoxItem

对ListBox的项ListBoxItem而言,其定义和使用方式和ListViewItem几乎相同,其区别只是在于其类型为ListBoxItem。这里只展示ListBoxItem的定义,如下:

                    <Style x:Key="FocusVisual">
                        <Setter Property="Control.Template">
                            <Setter.Value>
                                <ControlTemplate>
                                    <Rectangle Margin="0" SnapsToDevicePixels="true" Stroke="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}" StrokeThickness="0" StrokeDashArray="1 2"/>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>
                    <!-- Item项相关颜色 -->
                    <SolidColorBrush x:Key="Item.MouseOver.Background" Color="#DADADA"/>
                    <SolidColorBrush x:Key="Item.MouseOver.Border" Color="#3DDADADA"/>
                    <SolidColorBrush x:Key="Item.SelectedInactive.Background" Color="#FF0B7AFF"/>
                    <SolidColorBrush x:Key="Item.SelectedInactive.Border" Color="#3DDADADA"/>
                    <SolidColorBrush x:Key="Item.SelectedInactive.Foreground" Color="#FFFFFFFF"/>
                    <SolidColorBrush x:Key="Item.SelectedActive.Background" Color="#FF0B7AFF"/>
                    <SolidColorBrush x:Key="Item.SelectedActive.Border" Color="#FF0B7AFF"/>
                    <SolidColorBrush x:Key="Item.SelectedActive.Foreground" Color="#FFFFFFFF"/>

                    <!-- Item项样式 -->
                    <Style TargetType="{x:Type ListBoxItem}">
                        <Setter Property="HorizontalContentAlignment" Value="Center"/>

                        <Setter Property="SnapsToDevicePixels" Value="True"/>
                        <Setter Property="Padding" Value="4,1"/>
                        <Setter Property="Background" Value="Transparent"/>
                        <Setter Property="Foreground" Value="Black"/>
                        <Setter Property="BorderBrush" Value="Transparent"/>
                        <Setter Property="BorderThickness" Value="0"/>
                        <Setter Property="FocusVisualStyle" Value="{StaticResource FocusVisual}"/>
                        <Setter Property="Template">
                            <Setter.Value>
                                <ControlTemplate TargetType="{x:Type ListBoxItem}">
                                    <Border x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Padding="{TemplateBinding Padding}" SnapsToDevicePixels="true">
                                        <ContentControl x:Name="Ct" Foreground="{TemplateBinding Foreground}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
                                            <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                                        </ContentControl>
                                    </Border>
                                    <ControlTemplate.Triggers>
                                        <MultiTrigger>
                                            <MultiTrigger.Conditions>
                                                <Condition Property="IsMouseOver" Value="True"/>
                                            </MultiTrigger.Conditions>
                                            <Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.MouseOver.Background}"/>
                                            <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.MouseOver.Border}"/>
                                        </MultiTrigger>
                                        <MultiTrigger>
                                            <MultiTrigger.Conditions>
                                                <Condition Property="Selector.IsSelectionActive" Value="False"/>
                                                <Condition Property="IsSelected" Value="True"/>
                                            </MultiTrigger.Conditions>
                                            <Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.SelectedInactive.Background}"/>
                                            <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.SelectedInactive.Border}"/>
                                            <Setter Property="Foreground" TargetName="Ct" Value="{StaticResource Item.SelectedInactive.Foreground}"/>
                                        </MultiTrigger>
                                        <MultiTrigger>
                                            <MultiTrigger.Conditions>
                                                <Condition Property="Selector.IsSelectionActive" Value="True"/>
                                                <Condition Property="IsSelected" Value="True"/>
                                            </MultiTrigger.Conditions>
                                            <Setter Property="Background" TargetName="Bd" Value="{StaticResource Item.SelectedActive.Background}"/>
                                            <Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource Item.SelectedActive.Border}"/>
                                            <Setter Property="Foreground" TargetName="Ct" Value="{StaticResource Item.SelectedActive.Foreground}"/>
                                        </MultiTrigger>
                                        <Trigger Property="IsEnabled" Value="False">
                                            <Setter Property="TextElement.Foreground" TargetName="Bd" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                                        </Trigger>
                                    </ControlTemplate.Triggers>
                                </ControlTemplate>
                            </Setter.Value>
                        </Setter>
                    </Style>

总结

在自定义控件样式,要学会使用VS提供的XAML模板编辑。其使用方法,在XAML的设计界面找到控件,然后右键–>编辑样式–>编辑副本。然后按照要求编辑生成一个默认的副本样式,认真学习并根据副本去设计自己样式。我相信,只要你肯努力和善于思考,你会变得更优秀。


Over

每次记录一小步…点点滴滴人生路…

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值