WPF自定义控件10:FlatListView
在不少的应用程序中,有时候需要使用ListView控件来显示一组集合数据,这样可以从一组数据中进行选择,让数据更加的规范,便于统计和分析。本文将介绍一下自定义的列表控件FlatListView,它与FlatCheckBox实现过程非常类似,它是继承自ListView,但使用自定义的UI样式来美化界面。下面将详细介绍具体的实现细节。
1 WPF项目结构
基于之前创建的WPF示例项目,在其中创建一个新的关于FlatListView的项目文件。本质上,FlatListView是继承ListView控件,利用ListView控件自身的属性和方法,可以减少FlatListView实现的难度和复杂度。首先,给出本项目文件结构,如下图所示:
其中的Fonts目录下存放各种图标字体文件,Style目录下存放各种控件的UI 样式定义文件,FlatListView.xaml就是FlatListView控件的样式定义文件。另外,需要将其注册到Generic.xaml文件中,示例代码如下:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Yd.WpfControls">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Yd.WpfControls;component/Style/IconFont.xaml"/>
<ResourceDictionary Source="/Yd.WpfControls;component/Style/FlatButton.xaml"/>
<ResourceDictionary Source="/Yd.WpfControls;component/Style/FlatCheckBox.xaml"/>
<ResourceDictionary Source="/Yd.WpfControls;component/Style/FlatRadioButton.xaml"/>
<ResourceDictionary Source="/Yd.WpfControls;component/Style/ToggleButton.xaml"/>
<ResourceDictionary Source="/Yd.WpfControls;component/Style/FlatComboBox.xaml"/>
<ResourceDictionary Source="/Yd.WpfControls;component/Style/FlatTextBox.xaml"/>
<ResourceDictionary Source="/Yd.WpfControls;component/Style/FlatListView.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
2 WPF FlatListView实现
首先在Yd.WpfControls项目中添加一个类FlatListView.cs,它继承自ListView控件,示例代码如下:
using System.Windows;
using System.Windows.Controls;
namespace Yd.WpfControls
{
public class FlatListView : ListView
{
static FlatListView()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(FlatListView),
new FrameworkPropertyMetadata(typeof(FlatListView)));
}
}
}
FlatListView控件的UI样式主要就是依靠FlatListView.xaml文件进行定义的,示例代码如下:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Yd.WpfControls">
<!--图标字体引入-->
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Yd.WpfControls;component/Style/IconFont.xaml"/>
</ResourceDictionary.MergedDictionaries>
<SolidColorBrush x:Key="ListBox.Static.Background" Color="#34495e"/>
<SolidColorBrush x:Key="ListBox.Static.Border" Color="#34495e"/>
<SolidColorBrush x:Key="ListBox.Disabled.Background" Color="#FFFFFFFF"/>
<SolidColorBrush x:Key="ListBox.Disabled.Border" Color="#FFD9D9D9"/>
<Style x:Key="Flat_ListViewStyle" TargetType="{x:Type ListView}">
<Setter Property="Background" Value="{StaticResource ListBox.Static.Background}"/>
<Setter Property="BorderBrush" Value="{StaticResource ListBox.Static.Border}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
<Setter Property="ScrollViewer.PanningMode" Value="Both"/>
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListView}">
<Border x:Name="Bd" Background="{TemplateBinding Background}"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
Padding="1" SnapsToDevicePixels="true">
<ScrollViewer Focusable="false" Padding="{TemplateBinding Padding}">
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</ScrollViewer>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Background" TargetName="Bd" Value="{StaticResource ListBox.Disabled.Background}"/>
<Setter Property="BorderBrush" TargetName="Bd" Value="{StaticResource ListBox.Disabled.Border}"/>
</Trigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsGrouping" Value="true"/>
<Condition Property="VirtualizingPanel.IsVirtualizingWhenGrouping" Value="false"/>
</MultiTrigger.Conditions>
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="Flat_ItemHover" TargetType="{x:Type ListViewItem}">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Height" Value="30" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="Background" Value="#2ecc71" />
<Setter Property="Foreground" Value="Orange" />
<Setter Property="Cursor" Value="Hand" />
</Trigger>
<Trigger Property="IsSelected" Value="true">
<Setter Property="Background" Value="#2ecc71" />
<Setter Property="Foreground" Value="Yellow" />
<!--<Setter Property="FontWeight" Value="Bold" />-->
<Setter Property="Cursor" Value="Hand" />
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type local:FlatListView}" BasedOn="{StaticResource Flat_ListViewStyle}" >
<Setter Property="FontSize" Value="{x:Static local:FlatFonts.contentFontSize}"></Setter>
<Setter Property="Foreground" Value="White"></Setter>
<!-- Item Container样式 -->
<Setter Property="ItemContainerStyle" Value="{StaticResource Flat_ItemHover}"></Setter>
<Setter Property="Cursor" Value="Hand"/>
</Style>
</ResourceDictionary>
其中<Style TargetType="{x:Type local:FlatListView}" BasedOn="{StaticResource Flat_ListViewStyle}" 语句中的BasedOn表示继承关系,即一个新的Style可以通过BasedOn来继承,这样就可以更加方便的管理样式。另外,ListView每个Item容器的样式是通过ItemContainerStyle实现的,即 <Setter Property="ItemContainerStyle" Value="{StaticResource Flat_ItemHover}"></Setter> 。
3 WPF FlatListView测试
首先,需要重新生成一下项目文件,然后在WpfControls项目中添加Window8窗口,并添加自定义控件FlatListView,Window8.xaml示例代码如下:
<Window
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:WpfControls"
xmlns:WpfControls="clr-namespace:Yd.WpfControls;assembly=Yd.WpfControls" x:Class="WpfControls.Window8"
mc:Ignorable="d"
Title="Window8" Height="350" Width="500">
<Grid>
<WpfControls:FlatListView Name="flatListView" FontSize="13">
<ListView.ItemTemplate>
<DataTemplate>
<WrapPanel>
<TextBlock Text="{Binding Name}" />
<TextBlock Text=" (" />
<TextBlock Text="{Binding Counter}" Cursor="Hand"/>
<TextBlock Text=")" />
</WrapPanel>
</DataTemplate>
</ListView.ItemTemplate>
</WpfControls:FlatListView>
</Grid>
</Window>
其中的Name="flatListView"给控件起一个名称,这样可以在后台用C#来进行访问,下面给出后台初始化数据的示例代码:
using System;
using System.Collections.Generic;
using System.Linq;
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.Shapes;
namespace WpfControls
{
/// <summary>
/// Window8.xaml 的交互逻辑
/// </summary>
public partial class Window8 : Window
{
public Window8()
{
InitializeComponent();
List<Classz> items = new List<Classz>();
items.Add(new Classz() { Name = "Java语言编程", Counter = 42 });
items.Add(new Classz() { Name = "数据结构C++", Counter = 39 });
items.Add(new Classz() { Name = "FSharp编程基础", Counter = 13 });
flatListView.ItemsSource = items;
}
public class Classz
{
public string Name { get; set; }
public int Counter { get; set; }
}
}
}
运行界面如下:
- 点赞
- 收藏
- 关注作者
评论(0)