背水一战 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 之 控件(集 ...
随机推荐
- Python3实战系列之三(获取印度售后数据项目)
问题:续接上一篇.说干咱就干呀,勤勤恳恳写程序呀! 目标:实现第一个python程序的“Hello world!” 解决方案:新建一个项目Test,创建一个Test.py文件.在文件中实现打印出“He ...
- 提升HTML5的性能体验系列之二 列表流畅滑动
App的顶部一般有titlebar,下面是list.常见的一个需求是要在list滚动时,titlebar不动.这个简单的需求,实现起来其实并不简单. 在普通web上的做法是使用div的滚动条,把lis ...
- 常见CSS
.login_top_bg { background-image: url(/pcssc/images/login/login-top-bg.gif); background-repeat: repe ...
- Android Studio 老提示adb问题
Android Studio 老提示adb问题,restart后任然无解,最后发现某手机助手软件占用端口... 解决步骤: C:\Users\xxx>netstat -ano | findstr ...
- syslog系统日志、事件日志分析、EventLog Analyzer
syslog系统日志.事件日志分析.EventLog Analyzer Eventlog Analyzer是用来分析和审计系统及事件日志的管理软件,能够对全网范围内的主机.服务器.网络设备.数据库以及 ...
- 安装kafka 集群 步骤
1.下载 http://mirror.bit.edu.cn/apache/kafka/2.1.0/kafka_2.11-2.1.0.tgz 2.解压 tar -zxvf kafka_2.11-2.1 ...
- Ubuntu下删除卸载程序图标
Ubuntu下删除卸载程序图标 方法一:直接在终端输入命令alacarte.可以任意增.改.隐藏.显示菜单,但无法删除菜单,即使拥有root权限. 方法二:注意几个目录和文件./usr/share/a ...
- myeclipse cannot connect to vm
启动tomcat时,tomcat可以直接运行,而debug时弹出 解决方法:打开360安全卫士的功能大全找到修复网络(LSP)点击立即修复就可以使用debug
- vip导致的serverConnection closed by foreign host问题
问题描述: 应应用需求,设计搭建了一套带tokudb存储引擎的percona数据库,使用的是常见的双主架构.具体的架构如下图所示: 在172.20.32.x1上进行验证的时候出现了下面的问题: FHo ...
- AngularJS实战之cookie的读取
<!DOCTYPE html> <html ng-controller="cookies_controller"> <head> <tit ...