引言
本片文章分享一下之前遇到的WPF應(yīng)用在觸摸屏下使用時的兩個問題。
場景
具體場景就是一個配置界面, ScrollViewer
中包含一個StackPanel
然后縱向堆疊,已滾動的方式查看,然后包含多個 TextBlock
、 TextBox
以及DataGrid
,期間遇到了兩個問題:
- WPF在觸摸屏下,如果有滾動條(
ScrollViewer
)的情況下,默認(rèn)包含觸底反饋的功能,就是觸摸屏滑動到底或從底滑到頂,界面都會出現(xiàn)抖動的情況。 - 觸摸屏下,當(dāng)觸點處于
DataGrid
中時,無法滾動界面。
大概像這樣:
解決方案
觸底反饋抖動的問題
先來看第一個問題,這個其實是由于 ManipulationBoundaryFeedback
這個事件引起的:
最簡單的做法,就是在對應(yīng)包含ScrollViewer
的 UI 元素綁定它的反饋事件,然后在注冊方法中設(shè)置 e.Handled = true;
,這樣中斷了事件繼續(xù)冒泡或隧道傳播,比如這樣
// 在Xaml中,在對應(yīng)的 UIElement 上綁定ManipulationBoundaryFeedback="UIElement_ManipulationBoundaryFeedback"
//Code-Behind中 ,
private void UIElement_ManipulationBoundaryFeedback(object sender, ManipulationBoundaryFeedbackEventArgs e)
{
e.Handled = true;
}
但是這樣就需要你在每一個界面都添加該事件,代碼冗余,那么就可以使用附加屬性的方式,寫一個 ManipulationBoundaryFeedbackAttachedProperties
,各個界面直接使用,像這樣實現(xiàn):
public class ManipulationBoundaryFeedbackAttachedProperties
{
public static bool GetIsFeedback(DependencyObject obj)
{
return (bool)obj.GetValue(IsFeedbackProperty);
}
public static void SetIsFeedback(DependencyObject obj, bool value)
{
obj.SetValue(IsFeedbackProperty, value);
}
public static readonly DependencyProperty IsFeedbackProperty =
DependencyProperty.RegisterAttached("IsFeedback", typeof(bool), typeof(UIElement), new PropertyMetadata(true,
(s, e) =>
{
var target = s as UIElement;
if (target != null)
target.ManipulationBoundaryFeedback += Target_ManipulationBoundaryFeedback;
}));
private static void Target_ManipulationBoundaryFeedback(object sender, ManipulationBoundaryFeedbackEventArgs e)
{
var target = sender as UIElement;
if (target != null)
{
if (!GetIsFeedback(target))
{
e.Handled = true;
}
}
}
}
像這樣使用:
<ScrollViewer local:ManipulationBoundaryFeedbackAttachedProperties.IsFeedback="true">
...
</ScrollViewer>
這樣就完美解決了!
觸點在DataGrid中無法滾動的問題
這個問題,其實不光在 DataGrid
中有,觸點在 TextBox
、ListView
、ListBox
,這一類內(nèi)置有 ScrollViewer
的控件內(nèi),都有同樣的問題,而且不光是觸摸屏無法滾動,鼠標(biāo)滑輪也無法滾動。我處理這個問題的時候,是先處理的鼠標(biāo)滑輪無法滾動,處理方案就是根據(jù)鼠標(biāo)的偏移量,手動設(shè)置 ScrollViewer
的位置,如下:
private void DataGrid_MouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
{
var dataGrid = (DataGrid)sender;
// 獲取
var scrollViewer = GetScrollViewer(dataGrid);
if (scrollViewer != null)
{
if (scrollViewer.ViewportHeight + scrollViewer.VerticalOffset >= scrollViewer.ExtentHeight && e.Delta <= 0)
{
scrollViewer.LineDown();
}
else if (scrollViewer.VerticalOffset == 0 && e.Delta >= 0)
{
scrollViewer.LineUp();
}
}
}
public ScrollViewer GetScrollViewer(UIElement element)
{
if (element == null) return null;
ScrollViewer retour = null;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(element) && retour == null; i++)
{
if (VisualTreeHelper.GetChild(element, i) is ScrollViewer)
{
retour = (ScrollViewer)(VisualTreeHelper.GetChild(element, i));
}
else
{
retour = GetScrollViewer(VisualTreeHelper.GetChild(element, i) as UIElement);
}
}
return retour;
}
這樣就解決了,當(dāng)鼠標(biāo)位于 DataGrid
中時,使用滑輪界面無法滾動的問題,那么解決觸摸屏觸點在 DataGrid
中無法滾動的問題,也是一樣的思路,根據(jù)觸點的偏移量,模擬鼠標(biāo)滾輪的偏移量,在調(diào)用鼠標(biāo)滾動事件,模擬滾動,代碼如下:
private const double TouchMoveThreshold = 20; // 觸摸滾動的閾值
private Point lastTouchPosition; // 上一次觸摸的位置
private void DataGrid_PreviewTouchMove(object sender, System.Windows.Input.TouchEventArgs e)
{
// 獲取當(dāng)前觸摸位置
Point currentTouchPosition = e.GetTouchPoint((IInputElement)sender).Position;
// 計算觸摸移動的差值
double deltaY = currentTouchPosition.Y - lastTouchPosition.Y;
// 如果觸摸移動超過閾值,則模擬鼠標(biāo)滾動
if (Math.Abs(deltaY) > TouchMoveThreshold)
{
// 設(shè)置鼠標(biāo)滾動的差值
int mouseWheelDelta = (int)(deltaY / TouchMoveThreshold) * SystemParameters.WheelScrollLines;
// 創(chuàng)建模擬的鼠標(biāo)滾動事件參數(shù)
var mouseWheelEventArgs = new MouseWheelEventArgs(Mouse.PrimaryDevice, Environment.TickCount, mouseWheelDelta);
mouseWheelEventArgs.RoutedEvent = UIElement.MouseWheelEvent;
DataGrid_MouseWheel(sender, mouseWheelEventArgs);
// 更新上一次觸摸位置
lastTouchPosition = currentTouchPosition;
}
}
這樣,觸摸屏下,觸點在 DataGrid
中無法滾動的問題,就解決了。
小結(jié)
總的來說,大部分鼠標(biāo)和觸摸屏事件是類似的,但是有些場景下,可能兩者不通用的。所以可能需要自行測試一下,保證軟件的穩(wěn)定性。文章來源:http://www.zghlxwxcb.cn/news/detail-837926.html
本文中的解決方案不一定最完美的解決方案,如果各位看官有更好的解決方案,望不吝賜教。文章來源地址http://www.zghlxwxcb.cn/news/detail-837926.html
到了這里,關(guān)于WPF --- 觸摸屏下的兩個問題的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!