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

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls; namespace WpfDemo
{
public class MyWrapPanel : Panel
{
protected override System.Windows.Size MeasureOverride(System.Windows.Size availableSize)
{
Size currentLineSize = new Size();
Size panelSize = new Size(); foreach (UIElement element in base.InternalChildren)
{
element.Measure(availableSize);
Size desiredSize = element.DesiredSize; if (currentLineSize.Width + desiredSize.Width > availableSize.Width)
{
panelSize.Width = Math.Max(currentLineSize.Width, panelSize.Width);
panelSize.Height += currentLineSize.Height;
currentLineSize = desiredSize; if (desiredSize.Width > availableSize.Width)
{
panelSize.Width = Math.Max(desiredSize.Width, panelSize.Width);
panelSize.Height += desiredSize.Height;
currentLineSize = new Size();
}
}
else
{
currentLineSize.Width += desiredSize.Width;
currentLineSize.Height = Math.Max(desiredSize.Height, currentLineSize.Height);
}
} panelSize.Width = Math.Max(currentLineSize.Width, panelSize.Width);
panelSize.Height += currentLineSize.Height; return panelSize;
} protected override System.Windows.Size ArrangeOverride(System.Windows.Size finalSize)
{
int firstInLine = ;
int lineCount = ; Size currentLineSize = new Size(); double accumulatedHeight = ; UIElementCollection elements = base.InternalChildren;
double interval = 0.0;
for (int i = ; i < elements.Count; i++)
{ Size desiredSize = elements[i].DesiredSize; if (currentLineSize.Width + desiredSize.Width > finalSize.Width) //need to switch to another line
{
interval = (finalSize.Width - currentLineSize.Width) / (i - firstInLine + );
arrangeLine(accumulatedHeight, currentLineSize.Height, firstInLine, i, interval); accumulatedHeight += currentLineSize.Height;
currentLineSize = desiredSize; if (desiredSize.Width > finalSize.Width) //the element is wider then the constraint - give it a separate line
{
arrangeLine(accumulatedHeight, desiredSize.Height, i, ++i, );
accumulatedHeight += desiredSize.Height;
currentLineSize = new Size();
}
firstInLine = i;
lineCount++;
}
else //continue to accumulate a line
{
currentLineSize.Width += desiredSize.Width;
currentLineSize.Height = Math.Max(desiredSize.Height, currentLineSize.Height);
}
} if (firstInLine < elements.Count)
{
if (lineCount == )
{
interval = (finalSize.Width - currentLineSize.Width) / (elements.Count - firstInLine + );
}
arrangeLine(accumulatedHeight, currentLineSize.Height, firstInLine, elements.Count, interval);
} return finalSize;
} private void arrangeLine(double y, double lineHeight, int start, int end, double interval)
{
double x = ;
UIElementCollection children = InternalChildren;
for (int i = start; i < end; i++)
{
x += interval;
UIElement child = children[i];
child.Arrange(new Rect(x, y, child.DesiredSize.Width, lineHeight));
x += child.DesiredSize.Width;
}
}
}
}

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

 <Window x:Class="WpfDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:comm="clr-namespace:WpfDemo.CommonControls;assembly=WpfDemo.CommonControls"
xmlns:local="clr-namespace:WpfDemo"
Title="MainWindow" Height="" Width=""> <Grid>
<ListBox ItemsSource="{Binding DataSource}" ScrollViewer.HorizontalScrollBarVisibility="Disabled"
VerticalAlignment="Center" BorderThickness="">
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<local:MyWrapPanel IsItemsHost="True"/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Border HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Background="Green" BorderBrush="Yellow" BorderThickness="">
<TextBlock Text="{Binding CameraName}" Width="" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
<ListBox.Style>
<Style TargetType="{x:Type ListBox}"> </Style>
</ListBox.Style>
</ListBox>
</Grid>
</Window>

界面对应的ViewModel:

 using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Threading; namespace WpfDemo
{
public class MainWindowVM : NotifyPropertyBase
{
private DispatcherTimer timer;
public MainWindowVM()
{
DataSource = new ObservableCollection<WndViewModel>();
Colums = ;
for(int i =; i < ; ++i)
{
var temp = new WndViewModel()
{
CameraName = string.Format("Camera {0}", ++count),
};
DataSource.Add(temp);
}
//timer = new DispatcherTimer();
//timer.Interval = new TimeSpan(0, 0, 1);
//timer.Tick += timer_Tick;
//timer.Start();
} private int count = ;
void timer_Tick(object sender, EventArgs e)
{
var temp = new WndViewModel()
{
CameraName = string.Format("Camera {0}", ++count),
};
DataSource.Add(temp);
Console.WriteLine(temp.CameraName);
if (count <= )
{
Colums = count;
}
else if (count > )
{
count = ;
DataSource.Clear();
Colums = ;
}
} private int colums;
public int Colums
{
get { return colums; }
set
{
SetProperty(ref colums, value);
}
} private ObservableCollection<WndViewModel> dataSource;
public ObservableCollection<WndViewModel> DataSource
{
get { return dataSource; }
set
{
SetProperty(ref dataSource, value);
}
}
}
}

运行结果:

拉伸后:

WPF ListBox的进阶使用(二)的更多相关文章

  1. WPF ListBox的进阶使用(一)

    公司项目有个需求,UI界面支持动态平均分割界面,想了想便想到用ListBox来实现,用UniformGrid作为ListBox的ItemsPanelTemplate,通过动态改变UniformGrid ...

  2. WPF 4 DataGrid 控件(进阶篇二)

    原文:WPF 4 DataGrid 控件(进阶篇二)      上一篇<WPF 4 DataGrid 控件(进阶篇一)>中我们通过DataGridTemplateColumn 类自定义编辑 ...

  3. MVVM模式和在WPF中的实现(二)数据绑定

    MVVM模式解析和在WPF中的实现(二) 数据绑定 系列目录: MVVM模式解析和在WPF中的实现(一)MVVM模式简介 MVVM模式解析和在WPF中的实现(二)数据绑定 MVVM模式解析和在WPF中 ...

  4. 自定义WPF ListBox的选中项样式

    首先介绍一种简单地方法:就是通过自定义SystemColors类的参数来自定义WPF ListBox选择颜色的,SystemColors的HighlightBrushKey和HighlightText ...

  5. Android高手进阶教程(二十八)之---Android ViewPager控件的使用(基于ViewPager的横向相册)!!!

      分类: Android高手进阶 Android基础教程 2012-09-14 18:10 29759人阅读 评论(35) 收藏 举报 android相册layoutobjectclassloade ...

  6. Wireshark入门与进阶系列(二)

    摘自http://blog.csdn.net/howeverpf/article/details/40743705 Wireshark入门与进阶系列(二) “君子生非异也,善假于物也”---荀子 本文 ...

  7. WPF ListBox数据绑定

    本文来源 http://wshoufeng1989.blog.163.com/blog/static/202047033201282911633670/  风随影动的博客 使用数据库AllData , ...

  8. WPF的消息机制(二)- WPF内部的5个窗口之隐藏消息窗口

    目录 WPF的消息机制(一)-让应用程序动起来 WPF的消息机制(二)-WPF内部的5个窗口 (1)隐藏消息窗口 (2)处理激活和关闭的消息的窗口和系统资源通知窗口 (3)用于用户交互的可见窗口 (4 ...

  9. SpringBoot进阶教程(二十九)整合Redis 发布订阅

    SUBSCRIBE, UNSUBSCRIBE 和 PUBLISH 实现了 发布/订阅消息范例,发送者 (publishers) 不用编程就可以向特定的接受者发送消息 (subscribers). Ra ...

随机推荐

  1. 3DES加密及.NET弱密钥处理

    背景 智能pos机开发项目需要指定Key加密某些关键字符串.商定采用3DES加密算法. 实践 网海中很多.NET C#编写3DES加密的函数.采集一段简明.成熟的代码,归置于常用程序集.但当指定Key ...

  2. IOS初级:NSTimer

    @property (nonatomic, strong) NSTimer *timer; 添加定时器 self.timer = [NSTimer scheduledTimerWithTimeInte ...

  3. spring jpetstore研究入门(zz)

    spring jpetstore研究入门 分类: java2008-12-21 23:25 561人阅读 评论(2) 收藏 举报 springstrutsibatissearchweb框架servle ...

  4. python中的open( )函数

    函数原型 open(file, mode=‘r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True) buff ...

  5. Java第12章笔记

    如何定义 Java 中的方法 所谓方法,就是用来解决一类问题的代码的有序组合,是一个功能模块. 一般情况下,定义一个方法的语法是: 其中: //方法名为骆驼命名法 1. 访问修饰符:方法允许被访问的权 ...

  6. P3834 【模板】可持久化线段树 1(主席树)

    #include <bits/stdc++.h> #define read read() #define up(i,l,r) for(int i = (l);i <= (r);i++ ...

  7. mysql之表与表关联和表操作

    一 表于表之间的关联 foregin key:设置外键表于表之间建立关联. 多对一关联: 创建步骤,应该先创建好被关联的那一张表,然后再去创建关联的那一张表. 关联表的多条对应着被关联的那张表的一条记 ...

  8. 解决mysql默认的8小时自动断开连接

    语言:javaEE 框架:spring mvc+spring+mybatis 数据库:mysql8 WEB服务器:tomcat8 背景: 在试运营阶段发现发生“连接超时”异常 抛出异常: Cause: ...

  9. Javascript php 异常捕获

    JavaScript try 语句允许我们定义在执行时进行错误测试的代码块. catch 语句允许我们定义当 try 代码块发生错误时,所执行的代码块. JavaScript 语句 try 和 cat ...

  10. ThinkPHP redirect 传参

    重定向带参 $this->redirect('pay/under_line_success',array('order_id'=>$stuInfo),5,'页面跳转中….'); 第一个参数 ...