zoukankan      html  css  js  c++  java
  • WPF ListBox的进阶使用(二)

    项目中经常使用需要根据搜索条件查询数据,然后用卡片来展示数据。用卡片展示数据时,界面的宽度发生变化,希望显示的卡片数量也跟随变化。WrapPanel虽然也可以实现这个功能,但是将多余的部分都留在行尾,十分不美观,最好是能够将多余的宽度平分在每个ListBoxItem之间,比较美观,也符合项目需求。如下便是我自己实现的Panel:

      1 using System;
      2 using System.Collections.Generic;
      3 using System.Linq;
      4 using System.Text;
      5 using System.Threading.Tasks;
      6 using System.Windows;
      7 using System.Windows.Controls;
      8 
      9 namespace WpfDemo
     10 {
     11     public class MyWrapPanel : Panel
     12     {
     13         protected override System.Windows.Size MeasureOverride(System.Windows.Size availableSize)
     14         {
     15             Size currentLineSize = new Size();
     16             Size panelSize = new Size();
     17 
     18             foreach (UIElement element in base.InternalChildren)
     19             {
     20                 element.Measure(availableSize);
     21                 Size desiredSize = element.DesiredSize;
     22 
     23                 if (currentLineSize.Width + desiredSize.Width > availableSize.Width)
     24                 {
     25                     panelSize.Width = Math.Max(currentLineSize.Width, panelSize.Width);
     26                     panelSize.Height += currentLineSize.Height;
     27                     currentLineSize = desiredSize;
     28 
     29                     if (desiredSize.Width > availableSize.Width)
     30                     {
     31                         panelSize.Width = Math.Max(desiredSize.Width, panelSize.Width);
     32                         panelSize.Height += desiredSize.Height;
     33                         currentLineSize = new Size();
     34                     }
     35                 }
     36                 else
     37                 {
     38                     currentLineSize.Width += desiredSize.Width;
     39                     currentLineSize.Height = Math.Max(desiredSize.Height, currentLineSize.Height);
     40                 }
     41             }
     42 
     43             panelSize.Width = Math.Max(currentLineSize.Width, panelSize.Width);
     44             panelSize.Height += currentLineSize.Height;
     45 
     46             return panelSize;
     47         }
     48 
     49         protected override System.Windows.Size ArrangeOverride(System.Windows.Size finalSize)
     50         {
     51             int firstInLine = 0;
     52             int lineCount = 0;
     53 
     54             Size currentLineSize = new Size();
     55 
     56             double accumulatedHeight = 0;
     57 
     58             UIElementCollection elements = base.InternalChildren;
     59             double interval = 0.0;
     60             for (int i = 0; i < elements.Count; i++)
     61             {
     62 
     63                 Size desiredSize = elements[i].DesiredSize;
     64 
     65                 if (currentLineSize.Width + desiredSize.Width > finalSize.Width) //need to switch to another line
     66                 {
     67                     interval = (finalSize.Width - currentLineSize.Width) / (i - firstInLine + 2);
     68                     arrangeLine(accumulatedHeight, currentLineSize.Height, firstInLine, i, interval);
     69 
     70                     accumulatedHeight += currentLineSize.Height;
     71                     currentLineSize = desiredSize;
     72 
     73                     if (desiredSize.Width > finalSize.Width) //the element is wider then the constraint - give it a separate line                    
     74                     {
     75                         arrangeLine(accumulatedHeight, desiredSize.Height, i, ++i, 0);
     76                         accumulatedHeight += desiredSize.Height;
     77                         currentLineSize = new Size();
     78                     }
     79                     firstInLine = i;
     80                     lineCount++;
     81                 }
     82                 else //continue to accumulate a line
     83                 {
     84                     currentLineSize.Width += desiredSize.Width;
     85                     currentLineSize.Height = Math.Max(desiredSize.Height, currentLineSize.Height);
     86                 }
     87             }
     88 
     89             if (firstInLine < elements.Count)
     90             {
     91                 if (lineCount == 0)
     92                 {
     93                     interval = (finalSize.Width - currentLineSize.Width) / (elements.Count - firstInLine + 1);
     94                 }
     95                 arrangeLine(accumulatedHeight, currentLineSize.Height, firstInLine, elements.Count, interval);
     96             }
     97                 
     98 
     99             return finalSize;
    100         }
    101 
    102         private void arrangeLine(double y, double lineHeight, int start, int end, double interval)
    103         {
    104             double x = 0;
    105             UIElementCollection children = InternalChildren;
    106             for (int i = start; i < end; i++)
    107             {
    108                 x += interval;
    109                 UIElement child = children[i];
    110                 child.Arrange(new Rect(x, y, child.DesiredSize.Width, lineHeight));
    111                 x += child.DesiredSize.Width;
    112             }
    113         }
    114     }
    115 }

    接下来,便是将这个MyWrapPanel作为ListBox的ItemsPanelTemplate即可:

     1 <Window x:Class="WpfDemo.MainWindow"
     2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
     4         xmlns:comm="clr-namespace:WpfDemo.CommonControls;assembly=WpfDemo.CommonControls"
     5         xmlns:local="clr-namespace:WpfDemo"
     6         Title="MainWindow" Height="350" Width="525">
     7     
     8     <Grid>
     9         <ListBox ItemsSource="{Binding DataSource}" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
    10                  VerticalAlignment="Center" BorderThickness="0">
    11             <ListBox.ItemsPanel>
    12                 <ItemsPanelTemplate>
    13                     <local:MyWrapPanel IsItemsHost="True"/>
    14                 </ItemsPanelTemplate>
    15             </ListBox.ItemsPanel>
    16             <ListBox.ItemContainerStyle>
    17                 <Style TargetType="{x:Type ListBoxItem}">
    18                     <Setter Property="Template">
    19                         <Setter.Value>
    20                             <ControlTemplate TargetType="{x:Type ListBoxItem}">
    21                                 <Border HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="Green" BorderBrush="Yellow" BorderThickness="1">
    22                                     <TextBlock Text="{Binding CameraName}" Width="100" HorizontalAlignment="Center" VerticalAlignment="Center"/>
    23                                 </Border>
    24                             </ControlTemplate>
    25                         </Setter.Value>
    26                     </Setter>
    27                 </Style>
    28             </ListBox.ItemContainerStyle>
    29             <ListBox.Style>
    30                 <Style TargetType="{x:Type ListBox}">
    31                     
    32                 </Style>
    33             </ListBox.Style>
    34         </ListBox>
    35     </Grid>
    36 </Window>

    界面对应的ViewModel:

     1 using System;
     2 using System.Collections.Generic;
     3 using System.Collections.ObjectModel;
     4 using System.Linq;
     5 using System.Text;
     6 using System.Threading.Tasks;
     7 using System.Windows.Threading;
     8 
     9 namespace WpfDemo
    10 {
    11     public class MainWindowVM : NotifyPropertyBase
    12     {
    13         private DispatcherTimer timer;
    14         public MainWindowVM()
    15         {
    16             DataSource = new ObservableCollection<WndViewModel>();
    17             Colums = 1;
    18             for(int i =0; i < 60; ++i)
    19             {
    20                 var temp = new WndViewModel()
    21                 {
    22                     CameraName = string.Format("Camera {0}", ++count),
    23                 };
    24                 DataSource.Add(temp);
    25             }
    26             //timer = new DispatcherTimer();
    27             //timer.Interval = new TimeSpan(0, 0, 1);
    28             //timer.Tick += timer_Tick;
    29             //timer.Start();
    30         }
    31 
    32         private int count = 0;
    33         void timer_Tick(object sender, EventArgs e)
    34         {
    35             var temp = new WndViewModel()
    36             {
    37                 CameraName = string.Format("Camera {0}", ++count),
    38             };
    39             DataSource.Add(temp);
    40             Console.WriteLine(temp.CameraName);
    41             if (count <= 6)
    42             {
    43                 Colums = count;
    44             }
    45             else if (count > 100)
    46             {
    47                 count = 0;
    48                 DataSource.Clear();
    49                 Colums = 1;
    50             }
    51         }
    52 
    53         private int colums;
    54         public int Colums
    55         {
    56             get { return colums; }
    57             set
    58             {
    59                 SetProperty(ref colums, value);
    60             }
    61         }
    62 
    63         private ObservableCollection<WndViewModel> dataSource;
    64         public ObservableCollection<WndViewModel> DataSource
    65         {
    66             get { return dataSource; }
    67             set
    68             {
    69                 SetProperty(ref dataSource, value);
    70             }
    71         }
    72     }
    73 }

    运行结果:

    拉伸后:

  • 相关阅读:
    ubuntu网络配置相关知识(转载)
    git 冲突解决(转载)
    redmine后台运行命令
    CentOS配置网卡,重启网络显示:Device does not seem to be present(转载)
    解决Xshell和vim中文乱码(转载)
    REDHAT6.2配置yum源(64位)(转载)
    Doki Doki Literature Club ZOJ
    CONTINUE...? ZOJ
    Magic Points ZOJ
    Cash Machine (POJ 1276)(多重背包——二进制优化)
  • 原文地址:https://www.cnblogs.com/Johar/p/9562266.html
Copyright © 2011-2022 走看看