[源码下载]

背水一战 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的更多相关文章

  1. 背水一战 Windows 10 (50) - 控件(集合类): ItemsControl - 基础知识, 数据绑定, ItemsPresenter, GridViewItemPresenter, ListViewItemPresenter

    [源码下载] 背水一战 Windows 10 (50) - 控件(集合类): ItemsControl - 基础知识, 数据绑定, ItemsPresenter, GridViewItemPresen ...

  2. 背水一战 Windows 10 (51) - 控件(集合类): ItemsControl - 项模板选择器, 数据分组

    [源码下载] 背水一战 Windows 10 (51) - 控件(集合类): ItemsControl - 项模板选择器, 数据分组 作者:webabcd 介绍背水一战 Windows 10 之 控件 ...

  3. 背水一战 Windows 10 (53) - 控件(集合类): ItemsControl 的布局控件 - ItemsStackPanel, ItemsWrapGrid

    [源码下载] 背水一战 Windows 10 (53) - 控件(集合类): ItemsControl 的布局控件 - ItemsStackPanel, ItemsWrapGrid 作者:webabc ...

  4. 背水一战 Windows 10 (54) - 控件(集合类): ItemsControl 的布局控件 - OrientedVirtualizingPanel, VirtualizingStackPanel, WrapGrid

    [源码下载] 背水一战 Windows 10 (54) - 控件(集合类): ItemsControl 的布局控件 - OrientedVirtualizingPanel, VirtualizingS ...

  5. 背水一战 Windows 10 (49) - 控件(集合类): Pivot, Hub

    [源码下载] 背水一战 Windows 10 (49) - 控件(集合类): Pivot, Hub 作者:webabcd 介绍背水一战 Windows 10 之 控件(集合类) Pivot Hub 示 ...

  6. 背水一战 Windows 10 (48) - 控件(集合类): FlipView

    [源码下载] 背水一战 Windows 10 (48) - 控件(集合类): FlipView 作者:webabcd 介绍背水一战 Windows 10 之 控件(集合类) FlipView 示例Fl ...

  7. 背水一战 Windows 10 (55) - 控件(集合类): SemanticZoom, ISemanticZoomInformation

    [源码下载] 背水一战 Windows 10 (55) - 控件(集合类): SemanticZoom, ISemanticZoomInformation 作者:webabcd 介绍背水一战 Wind ...

  8. 背水一战 Windows 10 (56) - 控件(集合类): ListViewBase - 基础知识, 拖动项

    [源码下载] 背水一战 Windows 10 (56) - 控件(集合类): ListViewBase - 基础知识, 拖动项 作者:webabcd 介绍背水一战 Windows 10 之 控件(集合 ...

  9. 背水一战 Windows 10 (57) - 控件(集合类): ListViewBase - 增量加载, 分步绘制

    [源码下载] 背水一战 Windows 10 (57) - 控件(集合类): ListViewBase - 增量加载, 分步绘制 作者:webabcd 介绍背水一战 Windows 10 之 控件(集 ...

随机推荐

  1. sql 用Group by分组后,取每组的前几条记录

    转自:http://blog.163.com/jeson_lwj/blog/static/135761083201052411115783/ --查询每门课程的前2名成绩 CREATE TABLE S ...

  2. js 文件下载 进度条

    js: /** * 下载文件 - 带进度监控 * @param url: 文件请求路径 * @param params: 请求参数 * @param name: 保存的文件名 * @param pro ...

  3. web.xml 详细介绍(zz)

    web.xml 详细介绍 博客分类: CoreJava WebXMLServletJSPTomcat  http://mianhuaman.iteye.com/blog/1105522 1.启动一个W ...

  4. web API分类

    什么是Web API? Web API是网络应用程序接口.包含了广泛的功能,网络应用通过API接口,可以实现存储服务.消息服务.计算服务等能力,利用这些能力可以进行开发出强大功能的web应用. 分类 ...

  5. Selenium实战总结(webwiew下拉框定位)

    基于常见的两种下拉框的展示形式: 1.点击弹出下拉框: 2.鼠标移动弹出下拉框(move_to_element) 实例一[鼠标点击弹出的下拉框]: e.g百度首页的设置--高级搜索--时间: 导包: ...

  6. AJAX-URL-HTTP协议-缓存-DOM操作-HTML元素事件

    1.URL 1.URL的作用 用于来表示任意一个资源的位置(互联网上). 协议+主机名+文件目录结构+文件名称 2.详解 格式: <scheme>://<user>:<p ...

  7. rails gem更换ruby-china源

    查看gem源 gem sources -l 换添加源 gem sources --add https://gems.ruby-china.com/ 删除原来的rubygems源 gem sources ...

  8. C# Bitmap长宽参数构造的图片对象的每个像素ARGB都是0

    var img = new Bitmap(100 , 100); for (int i = 0; i < img.Width; i++) {   for (int j = 0; j < i ...

  9. top k问题

    1.top k问题 在海量数据处理中,经常会遇到的一类问题:在海量数据中找出出现频率最高的前k个数,或者从海量数据中找出最大的前k个数,这类问题通常被称为top K问题.例如,在搜索引擎中,统计搜索最 ...

  10. PHP源码编译安装

    cd php-5.6.0yum -y install libcurl-devel bzip2-devel zlib-devel libjpeg-devel libpng-devel freetype- ...