背水一战 Windows 10 (52) - 控件(集合类): ItemsControl - 自定义 ItemsControl, 自定义 ContentPresenter
作者:webabcd
介绍
背水一战 Windows 10 之 控件(集合类 - ItemsControl)
- 自定义 ItemsControl(自定义 GirdView 使其每个 item 占用不同大小的空间)
- 自定义 ContentPresenter 实现类似 GridViewItemPresenter 和 ListViewItemPresenter 的效果
示例
1、自定义 ItemsControl(自定义 GirdView 使其每个 item 占用不同大小的空间)
Controls/CollectionControl/ItemsControlDemo/MyItemsControlDemo.xaml
<Page
x:Class="Windows10.Controls.CollectionControl.ItemsControlDemo.MyItemsControlDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Windows10.Controls.CollectionControl.ItemsControlDemo"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"> <Page.Resources>
<DataTemplate x:Key="ItemTemplate">
<Grid Background="{Binding ColorValue}">
<Grid Background="Black" VerticalAlignment="Top" Opacity="0.7">
<TextBlock Text="{Binding ColorName}" />
</Grid>
</Grid>
</DataTemplate>
<Style x:Key="ItemContainerStyle" TargetType="GridViewItem">
<Setter Property="VerticalContentAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Margin" Value="0" />
<Setter Property="Padding" Value="0" />
</Style>
<ItemsPanelTemplate x:Key="ItemsPanel">
<VariableSizedWrapGrid MaximumRowsOrColumns="8" Orientation="Horizontal" ItemWidth="100" ItemHeight="100" />
</ItemsPanelTemplate> </Page.Resources> <Grid Background="Transparent" Margin="10 0 10 10">
<!--
使用 MyGridView 控件,其重写了 GridView 的 PrepareContainerForItemOverride() 方法,详见 MyGridView.cs
-->
<local:MyGridView x:Name="gridView" Width="812" VerticalAlignment="Top" HorizontalAlignment="Left"
ItemTemplate="{StaticResource ItemTemplate}"
ItemContainerStyle="{StaticResource ItemContainerStyle}"
ItemsPanel="{StaticResource ItemsPanel}"
IsItemClickEnabled="False"
SelectionMode="None">
</local:MyGridView>
</Grid>
</Page>
Controls/CollectionControl/ItemsControlDemo/MyItemsControlDemo.xaml.cs
/*
* ItemsControl - 集合控件(继承自 Control, 请参见 /Controls/BaseControl/ControlDemo/)
* protected virtual void PrepareContainerForItemOverride(DependencyObject element, object item); - 为 item 准备 container 时
* element - item 的 container
* item - item
*
*
* 本例用于演示如何使 GirdView 中的每个 item 占用不同大小的空间
* 1、布局控件要使用 VariableSizedWrapGrid(利用其 RowSpan 和 ColumnSpan 来实现 item 占用不同大小的空间),需要注意的是其并非是虚拟化布局控件
* 2、自定义 GridView,并重写 ItemsControl 的 protected override void PrepareContainerForItemOverride(DependencyObject element, object item) 方法
* 然后设置每个 item 的 VariableSizedWrapGrid.RowSpan 和 VariableSizedWrapGrid.ColumnSpan
*/ using System;
using System.Collections.Generic;
using System.Linq;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using System.Reflection; namespace Windows10.Controls.CollectionControl.ItemsControlDemo
{
public sealed partial class MyItemsControlDemo : Page
{
public MyItemsControlDemo()
{
this.InitializeComponent(); BindData();
} private void BindData()
{
Random random = new Random(); // 获取 Windows.UI.Colors 的全部数据
Type type = typeof(Colors);
List<ColorModel> colors = type.GetRuntimeProperties() // GetRuntimeProperties() 在 System.Reflection 命名空间下
.Select(c => new ColorModel
{
ColorName = c.Name,
ColorValue = new SolidColorBrush((Color)c.GetValue(null)),
ColSpan = random.Next(, ), // 此对象所占网格的列合并数
RowSpan = random.Next(, ) // 此对象所占网格的行合并数
})
.ToList(); // 绑定数据
gridView.ItemsSource = colors;
}
} /// <summary>
/// 用于数据绑定的对象
/// </summary>
public class ColorModel
{
public string ColorName { get; set; }
public SolidColorBrush ColorValue { get; set; } // 此对象所占的网格的列合并数
public int ColSpan { get; set; }
// 此对象所占的网格的行合并数
public int RowSpan { get; set; }
} /// <summary>
/// 自定义 GridView,重写 ItemsControl 的 protected override void PrepareContainerForItemOverride(DependencyObject element, object item) 方法
/// 用于指定 GridView 的每个 item 所占网格的列合并数和行合并数
/// </summary>
public class MyGridView : GridView
{
protected override void PrepareContainerForItemOverride(DependencyObject element, object item)
{
try
{
// 设置每个 item 的 VariableSizedWrapGrid.RowSpan 和 VariableSizedWrapGrid.ColumnSpan, 从而实现每个 item 占用不同大小的空间
// 仅为演示用,由于这里的 ColSpan 和 RowSpan 都是随机计算的,所以可能会出现空白空间 dynamic dynamicItem = item;
element.SetValue(VariableSizedWrapGrid.ColumnSpanProperty, dynamicItem.ColSpan);
element.SetValue(VariableSizedWrapGrid.RowSpanProperty, dynamicItem.RowSpan);
}
catch (Exception ex)
{
var ignore = ex; // 当有异常情况发生时(比如:item 没有 ColSpan 属性或 RowSpan 属性) element.SetValue(VariableSizedWrapGrid.ColumnSpanProperty, );
element.SetValue(VariableSizedWrapGrid.RowSpanProperty, );
}
finally
{
base.PrepareContainerForItemOverride(element, item);
}
}
}
}
2、自定义 ContentPresenter 实现类似 GridViewItemPresenter 和 ListViewItemPresenter 的效果
Controls/CollectionControl/ItemsControlDemo/MyItemPresenter.cs
/*
* 自定义 ContentPresenter 实现类似 GridViewItemPresenter 和 ListViewItemPresenter 的效果
*/ using System;
using Windows.Foundation;
using Windows.UI;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Animation;
using Windows.UI.Xaml.Shapes; namespace Windows10.Controls.CollectionControl.ItemsControlDemo
{
class MyItemPresenter : ContentPresenter
{
Panel _container = null; // item 的容器(即在 DataTemplate 中定义的根元素,在示例 MyItemPresenterDemo.xaml 中用的是 Grid)
Rectangle _pointerOverBorder = null; // 鼠标经过 item 时覆盖在 item 上的 rectangle
Rectangle _focusVisual = null; // 选中 item 时覆盖在 item 上的 rectangle Storyboard _pointerDownStoryboard = null; // 鼠标按下时的动画
Storyboard _pointerUpStoryboard = null; // 鼠标抬起时的动画 public MyItemPresenter()
: base()
{
base.Margin = new Thickness();
} // override OnApplyTemplate() - 应用控件模板时调用
protected override void OnApplyTemplate()
{
base.OnApplyTemplate(); _container = (Panel)VisualTreeHelper.GetChild(this, );
} // override GoToElementStateCore() - VisualState 转换时调用(此方法仅在自定义 ContentPresenter 并将其应用于 GridView 或 ListView 的 ItemContainerStyle 时才会被调用)
// stateName - VisualState 的名字
// useTransitions - 是否使用 VisualTransition 过渡效果
protected override bool GoToElementStateCore(string stateName, bool useTransitions)
{
base.GoToElementStateCore(stateName, useTransitions); switch (stateName)
{
// 正常状态
case "Normal":
HidePointerOverVisuals();
HideFocusVisuals();
if (useTransitions)
{
StopPointerDownAnimation();
}
break; // 选中状态
case "Selected":
case "PointerFocused":
ShowFocusVisuals();
if (useTransitions)
{
StopPointerDownAnimation();
}
break; // 取消选中状态
case "Unfocused":
HideFocusVisuals();
break; // 鼠标经过状态
case "PointerOver":
ShowPointerOverVisuals();
if (useTransitions)
{
StopPointerDownAnimation();
}
break; // 鼠标点击状态
case "Pressed":
case "PressedSelected":
if (useTransitions)
{
StartPointerDownAnimation();
}
break; default: break;
} return true;
} private void StartPointerDownAnimation()
{
if (_pointerDownStoryboard == null)
CreatePointerDownStoryboard(); _pointerDownStoryboard.Begin();
} private void StopPointerDownAnimation()
{
if (_pointerUpStoryboard == null)
CreatePointerUpStoryboard(); _pointerUpStoryboard.Begin();
} private void ShowFocusVisuals()
{
if (!FocusElementsAreCreated())
CreateFocusElements(); _focusVisual.Opacity = ;
} private void HideFocusVisuals()
{
if (FocusElementsAreCreated())
_focusVisual.Opacity = ;
} private void ShowPointerOverVisuals()
{
if (!PointerOverElementsAreCreated())
CreatePointerOverElements(); _pointerOverBorder.Opacity = ;
} private void HidePointerOverVisuals()
{
if (PointerOverElementsAreCreated())
_pointerOverBorder.Opacity = ;
} private void CreatePointerDownStoryboard()
{
/*
* 用这种方式为 item 实现鼠标按下的效果会报错(Attempted to read or write protected memory. This is often an indication that other memory is corrupt.),不知道为什么
* PointerDownThemeAnimation pointerDownAnimation = new PointerDownThemeAnimation();
* Storyboard.SetTarget(pointerDownAnimation, _container);
* Storyboard pointerDownStoryboard = new Storyboard();
* pointerDownStoryboard.Children.Add(pointerDownAnimation);
*/ DoubleAnimation da1 = new DoubleAnimation()
{
To = 0.9,
Duration = TimeSpan.FromMilliseconds()
};
DoubleAnimation da2 = new DoubleAnimation()
{
To = 0.9,
Duration = TimeSpan.FromMilliseconds()
};
Storyboard.SetTarget(da1, _container);
Storyboard.SetTargetProperty(da1, "(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)");
Storyboard.SetTarget(da2, _container);
Storyboard.SetTargetProperty(da2, "(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)");
if (!(_container.RenderTransform is TransformGroup))
{
TransformGroup Group = new TransformGroup();
Group.Children.Add(new ScaleTransform());
_container.RenderTransform = Group;
_container.RenderTransformOrigin = new Point(0.5, 0.5);
} _pointerDownStoryboard = new Storyboard();
_pointerDownStoryboard.Children.Add(da1);
_pointerDownStoryboard.Children.Add(da2);
_pointerDownStoryboard.Begin();
} private void CreatePointerUpStoryboard()
{
DoubleAnimation da1 = new DoubleAnimation()
{
To = ,
Duration = TimeSpan.FromMilliseconds()
};
DoubleAnimation da2 = new DoubleAnimation()
{
To = ,
Duration = TimeSpan.FromMilliseconds()
};
Storyboard.SetTarget(da1, _container);
Storyboard.SetTargetProperty(da1, "(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)");
Storyboard.SetTarget(da2, _container);
Storyboard.SetTargetProperty(da2, "(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleY)");
if (!(_container.RenderTransform is TransformGroup))
{
TransformGroup Group = new TransformGroup();
Group.Children.Add(new ScaleTransform());
_container.RenderTransform = Group;
_container.RenderTransformOrigin = new Point(0.5, 0.5);
} _pointerUpStoryboard = new Storyboard();
_pointerUpStoryboard.Children.Add(da1);
_pointerUpStoryboard.Children.Add(da2);
_pointerUpStoryboard.Begin();
} private void CreatePointerOverElements()
{
_pointerOverBorder = new Rectangle();
_pointerOverBorder.IsHitTestVisible = false;
_pointerOverBorder.Opacity = ;
// 这里把颜色写死了,仅为演示用,实际写的时候要摘出来写成依赖属性
_pointerOverBorder.Fill = new SolidColorBrush(Color.FromArgb(0x50, 0x50, 0x50, 0x50)); _container.Children.Insert(_container.Children.Count, _pointerOverBorder);
} private void CreateFocusElements()
{
_focusVisual = new Rectangle();
_focusVisual.IsHitTestVisible = false;
_focusVisual.Height = ;
_focusVisual.VerticalAlignment = VerticalAlignment.Bottom;
// 这里把颜色写死了,仅为演示用,实际写的时候要摘出来写成依赖属性
_focusVisual.Fill = new SolidColorBrush(Color.FromArgb(0xff, 0xff, 0x0, 0x0)); _container.Children.Insert(, _focusVisual);
} private bool FocusElementsAreCreated()
{
return _focusVisual != null;
} private bool PointerOverElementsAreCreated()
{
return _pointerOverBorder != null;
}
}
}
Controls/CollectionControl/ItemsControlDemo/MyItemPresenterDemo.xaml
<Page
x:Class="Windows10.Controls.CollectionControl.ItemsControlDemo.MyItemPresenterDemo"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Windows10.Controls.CollectionControl.ItemsControlDemo"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"> <Page.Resources>
<Style x:Key="MyGridViewItemPresenterTemplate" TargetType="GridViewItem">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="GridViewItem">
<!--
自定义 ContentPresenter 实现类似 GridViewItemPresenter 和 ListViewItemPresenter 的效果
-->
<local:MyItemPresenter />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Page.Resources> <Grid Background="Transparent">
<GridView x:Name="gridView" SelectionMode="Single" Margin="10 0 10 10"
ItemContainerStyle="{StaticResource MyGridViewItemPresenterTemplate}">
<GridView.ItemTemplate>
<DataTemplate>
<Grid Height="100" Width="100" Background="Blue">
<TextBlock x:Name="lblName" Text="{Binding Name}" Foreground="Yellow" />
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</Grid>
</Page>
Controls/CollectionControl/ItemsControlDemo/MyItemPresenterDemo.xaml.cs
/*
* 本例用于演示如何自定义 ContentPresenter 实现类似 GridViewItemPresenter 和 ListViewItemPresenter 的效果
*/ using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation;
using Windows10.Common; namespace Windows10.Controls.CollectionControl.ItemsControlDemo
{
public sealed partial class MyItemPresenterDemo : Page
{
public MyItemPresenterDemo()
{
this.InitializeComponent();
} protected override void OnNavigatedTo(NavigationEventArgs e)
{
gridView.ItemsSource = TestData.GetEmployees();
}
}
}
OK
[源码下载]
背水一战 Windows 10 (52) - 控件(集合类): ItemsControl - 自定义 ItemsControl, 自定义 ContentPresenter的更多相关文章
- 背水一战 Windows 10 (50) - 控件(集合类): ItemsControl - 基础知识, 数据绑定, ItemsPresenter, GridViewItemPresenter, ListViewItemPresenter
[源码下载] 背水一战 Windows 10 (50) - 控件(集合类): ItemsControl - 基础知识, 数据绑定, ItemsPresenter, GridViewItemPresen ...
- 背水一战 Windows 10 (51) - 控件(集合类): ItemsControl - 项模板选择器, 数据分组
[源码下载] 背水一战 Windows 10 (51) - 控件(集合类): ItemsControl - 项模板选择器, 数据分组 作者:webabcd 介绍背水一战 Windows 10 之 控件 ...
- 背水一战 Windows 10 (53) - 控件(集合类): ItemsControl 的布局控件 - ItemsStackPanel, ItemsWrapGrid
[源码下载] 背水一战 Windows 10 (53) - 控件(集合类): ItemsControl 的布局控件 - ItemsStackPanel, ItemsWrapGrid 作者:webabc ...
- 背水一战 Windows 10 (54) - 控件(集合类): ItemsControl 的布局控件 - OrientedVirtualizingPanel, VirtualizingStackPanel, WrapGrid
[源码下载] 背水一战 Windows 10 (54) - 控件(集合类): ItemsControl 的布局控件 - OrientedVirtualizingPanel, VirtualizingS ...
- 背水一战 Windows 10 (49) - 控件(集合类): Pivot, Hub
[源码下载] 背水一战 Windows 10 (49) - 控件(集合类): Pivot, Hub 作者:webabcd 介绍背水一战 Windows 10 之 控件(集合类) Pivot Hub 示 ...
- 背水一战 Windows 10 (48) - 控件(集合类): FlipView
[源码下载] 背水一战 Windows 10 (48) - 控件(集合类): FlipView 作者:webabcd 介绍背水一战 Windows 10 之 控件(集合类) FlipView 示例Fl ...
- 背水一战 Windows 10 (55) - 控件(集合类): SemanticZoom, ISemanticZoomInformation
[源码下载] 背水一战 Windows 10 (55) - 控件(集合类): SemanticZoom, ISemanticZoomInformation 作者:webabcd 介绍背水一战 Wind ...
- 背水一战 Windows 10 (56) - 控件(集合类): ListViewBase - 基础知识, 拖动项
[源码下载] 背水一战 Windows 10 (56) - 控件(集合类): ListViewBase - 基础知识, 拖动项 作者:webabcd 介绍背水一战 Windows 10 之 控件(集合 ...
- 背水一战 Windows 10 (57) - 控件(集合类): ListViewBase - 增量加载, 分步绘制
[源码下载] 背水一战 Windows 10 (57) - 控件(集合类): ListViewBase - 增量加载, 分步绘制 作者:webabcd 介绍背水一战 Windows 10 之 控件(集 ...
随机推荐
- rails 新建user的phonenumber字段
1.新建字段 //rails g migration add_字段名_to_表名 字段名:字段类型 rails g migration add_title_to_contents title:stri ...
- SHELL脚本取系统当前年月日问题 (去0)
1. #!/bin/bash tmonth=`date +%m`tyear=`date +%y`tday=`date +%d`day=`expr $tday + 0`month=`expr $tmon ...
- 2018.06.27Dual Core CPU(最小割)
Dual Core CPU Time Limit: 15000MS Memory Limit: 131072K Total Submissions: 26136 Accepted: 11270 Cas ...
- 如何将本地代码通过git上传到码云
ps:同部署到GitHub上一样 http://www.cnblogs.com/pcx105/p/7777932.html
- Java 获取最近时间
public static String getStatetime() throws ParseException{ SimpleDateFormat sdf = new SimpleDateForm ...
- HDU 5321 Beautiful Set (莫比乌斯反演 + 逆元 + 组合数学)
题意:给定一个 n 个数的集合,然后让你求两个值, 1.是将这个集合的数进行全排列后的每个区间的gcd之和. 2.是求这个集合的所有的子集的gcd乘以子集大小的和. 析:对于先求出len,len[i] ...
- Camtasia studio8.0破解方法
Camtasia Studio 8.0 注册说明: 1.安装时使用以下信息注册: 用户名: Honorary User密钥: GCABC-CPCCE-BPMMB-XAJXP-S8F6R 或者是 Nam ...
- Docker Swarm集群部署
一.系统环境 1)服务器环境 节点名称 IP 操作系统 内核版本 manager 172.16.60.95 CentOs7 4.16.1-1.el7.elrepo.x86_64 node-01 172 ...
- 视图,sql注入问题,事物,存储过程
视图:本质是一张虚拟的表数据来自select语句用途是保障原表安全 功能1:隐藏部分数据,开放指定数据功能2:因为视图可以将查询结果保存的特性,我们可以用视图来达到减少书写sql语句的功能 例如:se ...
- 百度地图的js导入及使用
做页面,地图可能会用到 1 导入百度地图的js库 <script type="text/javascript" src="http://api.map.baidu. ...