• WPF 自定义ItemsControl/ListBox/ListView控件样式


    一、前言

    ItemsControl、ListBox、ListView这三种控件在WPF中都可作为列表信息展示控件。我们可以通过修改这三个控件的样式来展示我们的列表信息。

    既然都是展示列表信息的控件,那他们有什么相同点和不同点呢。

    同:

      1、这三个控件都是列表型控件,可以进行列表绑定(ItemsSource);

      2、这三个控件均使用ItemsPresenter来展示列表信息;

    异:

      1、ListBox继承于ItemsControl,比ItemsControl一个Selector对象;

      2、ListView继承于ListBox,比ListBox多一个View属性。

    也就是说ItemsControl不支持列表项选择功能,ListBox支持单选、多选。ListView能以不同的视图形式展示列表信息。

    下面我们通过例子来展现:

    1.1、ItemsControl实现的图片选择预览控件

    控件的效果如下:

    下面贴上代码:

     <StackPanel Orientation="Horizontal" Margin=" 0 0" HorizontalAlignment="Center" VerticalAlignment="Center">
           <Grid>
                <Rectangle x:Name="rectangle" RadiusX="0" RadiusY="0" Width="50" Height="50" MouseLeftButtonUp="UpLoadCaptrue_Click" SnapsToDevicePixels="True" StrokeDashArray="3 3 3 3" StrokeThickness="1" Margin="5 0">
                     <Rectangle.Fill>
                           <ImageBrush ImageSource="/Images/UpLoad.png" Opacity="0.3" Stretch="Fill" Viewport="0.25 0.25 0.5 0.5"/>
                     </Rectangle.Fill>
                     <Rectangle.Style>
                           <Style TargetType="Rectangle">
                                 <Setter Property="Stroke" Value="#999999"/>
                                 <Style.Triggers>
                                      <Trigger Property="IsMouseOver" Value="true">
                                           <Setter Property="Stroke" Value="#1dc0a5"/>
                                      </Trigger>
                                 </Style.Triggers>
                            </Style>
                      </Rectangle.Style>
                </Rectangle>
            </Grid>
            <ScrollViewer ScrollViewer.HorizontalScrollBarVisibility="Auto" ScrollViewer.VerticalScrollBarVisibility="Hidden" Width="360">
                  <ItemsControl x:Name="itemsControl"   Background="Transparent" ItemsSource="{Binding }">
                         <ItemsControl.ItemsPanel>
                             <ItemsPanelTemplate>
                                 <StackPanel Orientation="Horizontal"/>
                              </ItemsPanelTemplate>
                         </ItemsControl.ItemsPanel>
                         <ItemsControl.ItemTemplate>
                              <DataTemplate>
                                   <Border>
                                        <StackPanel>
                                            <Grid Width="60" Height="60" SnapsToDevicePixels="True">
                                                <Border BorderBrush="#999999" Width="50" Height="50" BorderThickness="1" Margin="5 0">
                                                    <Image Source="{Binding}" Width="40" Height="40" HorizontalAlignment="Center" VerticalAlignment="Center"/>
                                                </Border>
                                                <Image Source="/Images/Close.png" Width="16" Height="16" MouseLeftButtonUp="ReMoveCaptrue_Click" HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0 2 0 0">
                                                    <Image.Style>
                                                        <Style TargetType="Image">
                                                            <Style.Triggers>
                                                                <Trigger Property="IsMouseOver" Value="true">
                                                                    <Setter Property="Effect">
                                                                        <Setter.Value>
                                                                            <DropShadowEffect ShadowDepth="0" Color="Red" Opacity="1" BlurRadius="5"/>
                                                                        </Setter.Value>
                                                                    </Setter>
                                                                </Trigger>
                                                            </Style.Triggers>
                                                        </Style>
                                                    </Image.Style>
                                                </Image>
                                            </Grid>
                                        </StackPanel>
                                    </Border>
                               </DataTemplate>
                         </ItemsControl.ItemTemplate>
                   </ItemsControl>
            </ScrollViewer>
     </StackPanel>

    上面ItemsControl设置了ItemsPanel,由于我们的列表展示是横向的,所以设置StackPanel,并将Orientation设置为Horizontal。

    里面有两个事件,添加图片UpLoadCaptrue_Click和移除图片ReMoveCaptrue_Click。代码如下:

    public MainWindow()
    {
          InitializeComponent();
          this.itemsControl.ItemsSource = Capture;
    }
    
    public ObservableCollection<string> Capture = new ObservableCollection<string>();
    
    /// <summary>
    /// 上传截图
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void UpLoadCaptrue_Click(object sender, MouseButtonEventArgs e)
    {
          OpenFileDialog logoSelected = new OpenFileDialog();
          logoSelected.Filter = "图片|*.jpg;*.png;*.bmp;*.gif";
          if (logoSelected.ShowDialog() ==true)
          {
               Capture.Add(logoSelected.FileName);
          }
    }
    
    /// <summary>
    /// 移除截图
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void ReMoveCaptrue_Click(object sender, MouseButtonEventArgs e)
    {
          Capture.Remove(((Image)sender).DataContext.ToString());
    }

     控件中用到的素材:

     

    1.2、基于ListBox实现用户列表展示

    下面的实例一般用于通讯软件用户列表展示。主要是通过修改ListBoxItem的样式来实现。

    先看下实现的效果:

    大体思路:先定义ListBoxStyle,定义ListBox的Style是为了实现去掉列表项的间隙,默认的ListBox里面有Padding值。我们把Padding改为0;然后定义ListBoxItem项的Style样式,因为我们是通过绑定数据的方式呈现,因此对于需要动态显示的值我们把它放到一个类中。

     public List<UserInfo> UserList { get; set; }
    
     public class UserInfo
    {
             public Brush UserBackground { get; set; }
             public string Header { get; set; }
             public string Name { get; set; }
             public string Info { get; set; }
             public int Count { get; set; }
    }

    ListBoxItem样式代码如下:

     <Style x:Key="UserInfoStyle" TargetType="{x:Type ListBoxItem}">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ListBoxItem}">
                            <Grid Height="50" x:Name="grid">
                                <Border Background="{Binding UserBackground}" Width="40" Height="40" CornerRadius="4" HorizontalAlignment="Left" Margin="5 0 0 0">
                                    <TextBlock Text="{Binding Header}" FontSize="23" Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                                </Border>
                                <TextBlock Text="{Binding Name}" Margin="55 7 0 0" FontSize="13"/>
                                <TextBlock Text="{Binding Info}" Foreground="#808080" Margin="55 30 0 0"/>
                                <TextBlock Text="{Binding Count,StringFormat={}{0}人}" Foreground="#808080" HorizontalAlignment="Right" VerticalAlignment="Center" Margin="0 0 5 0"/>
                            </Grid>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsMouseOver" Value="true">
                                    <Setter TargetName="grid" Property="Background" Value="#fceeb9"/>
                                </Trigger>
                                <Trigger Property="Selector.IsSelected" Value="true">
                                    <Setter TargetName="grid" Property="Background" Value="#fae388"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>

    ListBox样式代码如下:

    <ListBox BorderThickness="1" ItemContainerStyle="{StaticResource UserInfoStyle}" x:Name="UserInfoList" BorderBrush="#eaeaeb" Background="Transparent" Width="280" Height="300" Margin="50 5 0 0">
            <ListBox.Style>
                  <Style TargetType="ListBox">
                        <Setter Property="Template">
                                <Setter.Value>
                                    <ControlTemplate TargetType="ListBox">
                                        <Border x:Name="Bd"  BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Padding="0">
                                            <ScrollViewer Focusable="False">
                                                <ItemsPresenter />
                                            </ScrollViewer>
                                        </Border>
    
                                    </ControlTemplate>
                             </Setter.Value>
                     </Setter>
                </Style>
          </ListBox.Style>
    </ListBox>

    后台C#代码初始化数据,及设定数据源:

    UserList = new List<UserInfo>()
                {
                    new UserInfo(){
                        UserBackground=new SolidColorBrush((Color)ColorConverter.ConvertFromString("#ff9f4c")),
                        Header="",
                        Name="DESKTOP-0N",
                        Info="我要像风一样自由!",
                        Count=3
                    },
                    new UserInfo(){
                         UserBackground=new SolidColorBrush((Color)ColorConverter.ConvertFromString("#ff9f4c")),
                        Header="",
                        Name="张三丰",
                        Info="我要像风一样自由!",
                        Count=5
                    },
                    new UserInfo(){
                         UserBackground=new SolidColorBrush((Color)ColorConverter.ConvertFromString("#9d9d9d")),
                        Header="",
                        Name="鬼见愁",
                        Info="我要像风一样自由!",
                        Count=2
                    },
                };
                this.UserInfoList.ItemsSource = UserList;

    1.3、ListBoxView列表信息展示

    ListBoxView信息展示有点像DataGrid控件,以下为ListBoxView基本样式代码:

      <Style x:Key="ListViewItemStyle" TargetType="{x:Type ListViewItem}">
                <Setter Property="HorizontalContentAlignment" Value="Stretch" />
                <Setter Property="Foreground" Value="Black"/>
                <Setter Property="BorderThickness" Value="0"/>
                <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">
                                <GridViewRowPresenter VerticalAlignment="Center" Content="{TemplateBinding Content}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsSelected" Value="True">
                                    <Setter Property="Background" TargetName="Bd" Value="#FF866C"></Setter>
                                    <Setter Property="Foreground" Value="White"></Setter>
                                </Trigger>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter Property="Background" TargetName="Bd" Value="#FFEAE4"></Setter>
                                    <Setter Property="Foreground" Value="Black"></Setter>
                                </Trigger>
                                <Trigger Property="Height" Value="Auto">
                                    <Setter Property="MinHeight" Value="35" />
                                </Trigger>
                                <Trigger Property="IsEnabled" Value="False">
                                    <Setter Property="Opacity" Value="0.5"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
    
            <Style x:Key="ListViewStyle1" TargetType="{x:Type ListView}">
                <Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
                <Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
                <Setter Property="VirtualizingStackPanel.IsVirtualizing" Value="True"></Setter>
                <Setter Property="VirtualizingStackPanel.VirtualizationMode" Value="Recycling" />
                <Setter Property="ScrollViewer.IsDeferredScrollingEnabled" Value="False" />
                <Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
                <Setter Property="ScrollViewer.PanningMode" Value="Both"/>
                <Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
                <Setter Property="ItemContainerStyle" Value="{StaticResource ListViewItemStyle}"/>
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type ListView}">
                            <ScrollViewer Padding="{TemplateBinding Padding}" Style="{DynamicResource {x:Static GridView.GridViewScrollViewerStyleKey}}">
                                <ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                            </ScrollViewer>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsGrouping" Value="true">
                                    <Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
           
            <Style x:Key="GridViewColumnHeaderStyle" TargetType="{x:Type GridViewColumnHeader}">
                <Setter Property="Background" Value="#FFEAE4" />
                <Setter Property="Template" >
                    <Setter.Value>
                        <ControlTemplate TargetType="{x:Type GridViewColumnHeader}">
                            <Grid SnapsToDevicePixels="True" >
                                <Border x:Name="HeaderBorder" BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}">
                                    <Grid>
                                        <Grid.RowDefinitions>
                                            <RowDefinition MaxHeight="7"/>
                                            <RowDefinition/>
                                        </Grid.RowDefinitions>
                                        <Border Padding="{TemplateBinding Padding}" Grid.RowSpan="2">
                                            <ContentPresenter x:Name="HeaderContent" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" RecognizesAccessKey="True" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
                                        </Border>
                                    </Grid>
                                </Border>
                                <Canvas>
                                    <Thumb x:Name="PART_HeaderGripper">
                                        <Thumb.Style>
                                            <Style TargetType="{x:Type Thumb}">
                                                <Setter Property="Canvas.Right" Value="-9"/>
                                                <Setter Property="Width" Value="18"/>
                                                <Setter Property="Height" Value="{Binding ActualHeight, RelativeSource={RelativeSource TemplatedParent}}"/>
                                                <Setter Property="Padding" Value="0"/>
                                                <Setter Property="Background" Value="White"/>
                                                <Setter Property="Template">
                                                    <Setter.Value>
                                                        <ControlTemplate TargetType="{x:Type Thumb}">
                                                            <Border Background="Transparent" Padding="{TemplateBinding Padding}">
                                                                <Rectangle Fill="{TemplateBinding Background}" HorizontalAlignment="Center" Width="1"/>
                                                            </Border>
                                                        </ControlTemplate>
                                                    </Setter.Value>
                                                </Setter>
                                            </Style>
                                        </Thumb.Style>
                                    </Thumb>
                                </Canvas>
                            </Grid>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsMouseOver" Value="True">
                                    <Setter Property="Background" TargetName="HeaderBorder" Value="#FF866B"/>
                                    <Setter Property="Background" TargetName="PART_HeaderGripper" Value="Transparent"/>
                                </Trigger>
                                <Trigger Property="IsPressed" Value="True">
                                    <Setter Property="Background" TargetName="HeaderBorder" Value="#FF866B"/>
                                    <Setter Property="Visibility" TargetName="PART_HeaderGripper" Value="Hidden"/>
                                </Trigger>
                                <Trigger Property="Height" Value="Auto">
                                    <Setter Property="MinHeight" Value="35"/>
                                </Trigger>
                                <Trigger Property="IsEnabled" Value="False">
                                    <Setter Property="Opacity" Value="0.5"/>
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>

    引用示例:

     <ListView x:Name="ListView"  Style="{StaticResource ListViewStyle1}" Width="500">
                    <ListView.View>
                        <GridView  ColumnHeaderContainerStyle="{StaticResource GridViewColumnHeaderStyle}">
                            <GridViewColumn Header="序号" DisplayMemberBinding="{Binding Num}" Width="100"/>
                            <GridViewColumn Header="名称" DisplayMemberBinding="{Binding Name}"  Width="100"/>
                            <GridViewColumn Header="Template"  Width="auto">
                                <GridViewColumn.CellTemplate>
                                    <DataTemplate>
                                        <CheckBox Content="{Binding Template}"></CheckBox>
                                    </DataTemplate>
                                </GridViewColumn.CellTemplate>
                            </GridViewColumn>
                        </GridView>
                    </ListView.View>
                </ListView>

    后台代码需要给ListBoxView绑定数据:

     public partial class MainWindow : Window
        {
            public MainWindow()
            {
                InitializeComponent();
                ListViewDataList = new List<ListViewData>();
                for (int i = 0; i < 10; i++)
                {
                    ListViewDataList.Add(new ListViewData()
                    {
                        Num = i,
                        Name = "No_" + i.ToString(),
                        Template="Temlate:"+i.ToString()
                    });
                }
                this.ListView.ItemsSource = ListViewDataList;
            }
            public List<ListViewData> ListViewDataList { get; set; }
            public class ListViewData
            {
                public int Num { get; set; }
                public string Name { get; set; }
                public string Template { get; set; }
            }
    
        }

     效果图:

    所有代码已经上传到github:https://github.com/cmfGit/WpfDemo.git

  • 相关阅读:
    C++入门经典-例3.4-根据成绩划分等级
    C++入门经典-例3.3-if-else语句的奇偶性判别
    C++入门经典-例3.2-根据分数判断是否优秀
    C++入门经典-例3.1-判断输入的数字是否为奇数
    C++入门经典-例2.17强制类型转换
    C++入门经典-例2.16-隐式类型转换
    C++入门经典-例2.15-逗号表达式的应用
    C++入门经典-例2.14-使用移位运算
    C++入门经典-例2.13-左移运算
    Spring之Bean管理------注解方式
  • 原文地址:https://www.cnblogs.com/xiaomingg/p/8733421.html
Copyright © 2020-2023  润新知