【WinRT】让控件飞,WinRT 中实现 web 中的 dragable 效果
由于在 xaml 体系中,控件没有传统 WebForm 中的 Left、Top、Right、Bottom 这些属性,取而代之的是按比例(像 Grid)等等的响应布局。但是,传统的这些设置 Left、Top 的硬编码的需求仍然存在,所以,在所有的 xaml 体系中,均存在一个代替的控件——Canvas。本文基于 Canvas 来实现控件的拖拉效果。
在整个控件拖拉的过程当中,可以分解为 3 个部分,第一个部分是输入设备点击控件,第二个部分是保持按下的状态下移动输入设备,第三个部分是释放输入设备。那么,就必须对这 3 个过程做出相应的逻辑处理。
那么,有一个重要的问题来了,如何标识控件是否处于拖拉状态。C# 不像 javascript 那样,能够随便修改对象,添加属性。但是,这难不倒微软的工程师,在 xaml 体系中,有附加属性这样一个东西。
public static class DragHelper
{
public static readonly DependencyProperty IsPraggingProperty = DependencyProperty.RegisterAttached("IsDragging", typeof(bool), typeof(DragHelper), new PropertyMetadata(false));
}
这里使用 IsDragging 来标识控件是否处于拖放过程中。
然后接下来我们需要一个初始化的方法来使控件可以拖放。
public static class DragHelper
{
public static bool Dragable(this UIElement control)
{
// TODO
}
}
这里使用扩展方法,使调用方简洁一些。该方法返回一个布尔值,指示是否操作成功。对于控件的父对象为 Canvas 的,我们返回 true,否则返回 false。
public static class DragHelper
{
public static bool Dragable(this UIElement control)
{
if(control==null)
{
throw new ArgumentNullException("control");
}
if(VisualTreeHelper.GetParent(control) is Canvas)
{
// TODO
return true;
}
else
{
return false;
}
}
}
由于控件没有所谓的 Parent 属性,因此我们需要使用可视树来获取父控件。
接下来将一开始的 3 个过程映射到相应的对象事件。
1、输入设备点击控件:UIElement.PointertPressed
2、输入设备移动:Window.Current.CoreWindow.PointerMoved
3、释放输入设备:Window.Current.CoreWindow.PointerReleased
public static bool Dragable(this UIElement control)
{
// null 判断,参考上面
if(VisualTreeHelper.GetParent(control) is Canvas)
{
control.PointerPressed+=(sender,e)=>
{
// 设置控件进入拖放状态。
control.SetValue(IsDraggingProperty, true);
// TODO
};
var coreWindow = Window.Current.CoreWindow;
coreWindow.PointerMoved+=(sender,args)=>
{
if((bool)control.GetValue(IsDraggingProperty))
{
// TODO
}
};
coreWindow.PointerReleased+=(sender,args)=>
{
// TODO
}; return true;
}
else
{
return false;
}
}
接下来,在移动的过程中,我们需要不断设置控件的 Left、Top 这两个 Canvas 的附加属性来达到拖放的效果。可以通过
args.CurrentPoint.Position
来获得输入设备当前的位置。那么每一次设置的位置就等于初始位置加上当次位置。
总体代码:
public static class DragHelper
{
public static readonly DependencyProperty IsDraggingProperty = DependencyProperty.RegisterAttached(
"IsDragging", typeof(bool), typeof(DragHelper), new PropertyMetadata(false)); public static readonly DependencyProperty StartLeftProperty = DependencyProperty.RegisterAttached("StartLeft",
typeof(double), typeof(DragHelper), new PropertyMetadata(0.0d)); public static readonly DependencyProperty StartTopProperty = DependencyProperty.RegisterAttached("StartTop",
typeof(double), typeof(DragHelper), new PropertyMetadata(0.0d)); public static readonly DependencyProperty StartPositionProperty =
DependencyProperty.RegisterAttached("StartPosition", typeof(Point), typeof(DragHelper),
new PropertyMetadata(default(Point))); public static bool Dragable(this UIElement control)
{
if (control == null)
{
throw new ArgumentNullException("control");
}
if (VisualTreeHelper.GetParent(control) is Canvas)
{
control.PointerPressed += (sender, e) =>
{
control.SetValue(IsDraggingProperty, true);
control.SetValue(StartLeftProperty, Canvas.GetLeft(control));
control.SetValue(StartTopProperty, Canvas.GetTop(control));
control.SetValue(StartPositionProperty, e.GetCurrentPoint(null).Position);
};
var coreWindow = Window.Current.CoreWindow;
coreWindow.PointerMoved += (sender, args) =>
{
if ((bool)control.GetValue(IsDraggingProperty))
{
var currentPosition = args.CurrentPoint.Position;
var startPosition = (Point)control.GetValue(StartPositionProperty);
var deltaX = currentPosition.X - startPosition.X;
var deltaY = currentPosition.Y - startPosition.Y;
var startLeft = (double)control.GetValue(StartLeftProperty);
var startTop = (double)control.GetValue(StartTopProperty);
Canvas.SetLeft(control, startLeft + deltaX);
Canvas.SetTop(control, startTop + deltaY);
}
};
coreWindow.PointerReleased += (sender, args) => control.SetValue(IsDraggingProperty, false); return true;
}
else
{
return false;
}
}
}
}
在第一步保存控件相关信息到附加属性当中便于移动状态使用。
效果:

应用:
例如开发一个 ListView 返回顶部的小插件。

由于 Button 会吞掉 PointerPressed 这个事件,因此这里使用了 Border 来模拟。
Border 相关的 xaml 代码:
<Canvas>
<Border x:Name="btn"
Canvas.Left="300"
Canvas.Top="400"
Width="50"
Height="50"
CornerRadius="50"
BorderBrush="Gray"
BorderThickness="3"
Background="Red"
Tapped="Btn_OnTapped">
<TextBlock Text="顶"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontSize="25"
Foreground="Gold" />
</Border>
</Canvas>
ListView 滚回到顶部的代码。
private void Btn_OnTapped(object sender, TappedRoutedEventArgs e)
{
// Lvw 为 ListView 控件。
var item = Lvw.Items.FirstOrDefault();
if (item != null)
{
Lvw.ScrollIntoView(item);
}
}
【WinRT】让控件飞,WinRT 中实现 web 中的 dragable 效果的更多相关文章
- ASP.NET中共有哪几种类型的控件?其中,HTML控件、HTML服务器控件和WEB服务器控件之间有什么区别
ASP.NET的控件包括WEB服务器控件.WEB用户控件.WEB自定义控件.HTML服务器控件和HTML控件.HTML控件.HTML服务器控件和WEB服务器控件之间的区别如下所示.q HTM ...
- 背水一战 Windows 10 (65) - 控件(WebView): 对 WebView 中的内容截图, 通过 Share Contract 分享 WebView 中的被选中的内容
[源码下载] 背水一战 Windows 10 (65) - 控件(WebView): 对 WebView 中的内容截图, 通过 Share Contract 分享 WebView 中的被选中的内容 作 ...
- WPF中Popup控件在Win7以及Win10等中的对齐点方式不一样的解决方案 - 简书
原文:WPF中Popup控件在Win7以及Win10等中的对齐点方式不一样的解决方案 - 简书 最近项目中使用弹出控件Popup,发现弹出框的对齐方式在不同的系统中存在不同(Popup在win10上是 ...
- 客户端的javascript改变了asp.net webform页面控件的值,后台代码中如何获取修改后的值。
客户端的javascript改变了asp.net webform页面控件的值,后台代码中如何获取修改后的值. 无论是什么的html控件,只要加上了runat="server" ...
- WPF封装控件时 检测是否在设计模式中
原文:WPF封装控件时 检测是否在设计模式中 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/Vblegend_2013/article/detail ...
- 安卓,网页控件,显示网页 Android, web controls, display web pages
安卓,网页控件,显示网页Android, web controls, display web pages 作者:韩梦飞沙 Author:han_meng_fei_sha 邮箱:313134555@qq ...
- wpf的UserControl用户控件怎么添加到Window窗体中
转载自 http://www.cnblogs.com/shuang121/archive/2013/01/09/2853591.html 我们来新建一个用户控件UserControl1.xaml &l ...
- 解决Select2控件不能在jQuery UI Dialog中不能搜索的bug
本文使用博客园Markdown编辑器进行编辑 1.问题呈现 项目中使用了jQuery UI的Dialog控件,一般用来处理需要提示用户输入或操作的简单页面.逻辑是修改一个广告的图片和标题. 效果截图如 ...
- ActiveX控件打包成Cab置于网页中自动下载安装(转载)
原文出自http://www.iteye.com/topic/110834 [背景] 做过ActiveX控件的朋友都知道,要想把自己做的ActiveX控件功能放在自己的网页上使用,那么用户在客户端就必 ...
随机推荐
- 关于访问asp.net网站时登录后的奇怪问题
登录后,地址栏地址变成了 http://www.XXXX.com/(F(HDc3otfFs0wkZu4P4CjZ50Qkck2q8aekR3g6F0m_NRZRo7kt7XQ6CjAFBR4PR8kZ ...
- jquery 不选择第一个
参考 https://zhidao.baidu.com/question/174343639.html th:not(':first')
- IE6、IE7、Firefox中margin问题及input解决办法
margin不居中的问题 .div{ margin:10px;/*ff*/ *margin:15px;/*ie7*/ _margin:15px;/*ie6*/ 尺寸会变为正常的两倍,按道理应为5px ...
- Sum of Consecutive Prime Numbers
Sum of Consecutive Prime Numbers http://poj.org/problem?id=2739 Time Limit: 1000MS Memory Limit: 6 ...
- Finding Hotels
Finding Hotels http://acm.hdu.edu.cn/showproblem.php?pid=5992 Time Limit: 2000/1000 MS (Java/Others) ...
- 【校招面试 之 剑指offer】第16题 数值的整数次方
方法1:直接求解,但是要注意特殊情况的处理:即当指数为负,且底数为0的情况. #include<iostream> using namespace std; template<typ ...
- 自定义 tableviewheader 高度显示不正常
BUG : 自定义的Xib View, 设置为tableview分区头的时候 tableview 如果是plain 模式, 设置 sectionHeader, sectionHeader会成为悬浮 ...
- Mybatis的分页插件PageHelp:Page对象中的pageSize等属性无法序列化,无法转换为json字符串
Page<User> page = new Page<>(); User user = new User(); user.setAge(20); ...
- 5-分西瓜差最小(背包 || dfs)
/* zb立刻下定决心买了一堆西瓜.当他准备把西瓜送给C小加和never的时候,遇到了一个难题,never和C小加不在一块住,只能把西瓜分成两堆给他们,为了对每个人都公平,他想让两堆的重量之差最小 ...
- php5.4 trait 理解与学习
Trait 是 php5.4引入的新特性,手册上说的一大段没看懂,这里直接来过来. Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制.Trait 为了减少单继承语言的限制,使开发人员 ...