前言
做wpf開發(fā)不像mfc控件的刷新相對同步,wpf的控件改變寬高或者可見性后在下一行代碼不會立刻看到效果,而且也沒有一種事件可以獲取確切的界面刷新后的時機。如果只是進行延遲等待,在不同機器效果是不同的,而且也并沒有具體標識說明已刷新界面,這就導致某些場景的功能實現(xiàn)起來會比較困難。本文提供一種獲取控件真正界面刷新時機的方法。
一、為何要獲取刷新時機?
例子一、隱藏控件后截屏
需要隱藏控件后截屏,直接修改Visibility后截屏是不行的,控件不會立刻隱藏,所以會截到控件的畫面。如果不能獲取到真正的刷新時機,那就這能延時等待,但延時是不穩(wěn)定的,至少筆者就遇到了延時500毫秒再截屏,依然在生產(chǎn)環(huán)境有客戶遇到了截到控件畫面的bug。
例子二、修改控件大小后做計算
有一段邏輯需要根據(jù)控件大小做計算,使用的是ActualWidth、ActualHeight。在這段邏輯前剛好有修改大小的代碼,但此時修改Width、Height之后ActualWidth、ActualHeight不會立刻改變,需要等到界面刷新時會改變,這就會導致計算數(shù)值不正確。這種場景很可能難以使用延時。
二、如何實現(xiàn)?
1.使用動畫
wpf的動畫有個完成事件,我們通過這個事件就可以獲取繪制完一幀的時機。
//創(chuàng)建
var da = new DoubleAnimation(1, 0, new Duration(TimeSpan.FromMilliseconds(1)), FillBehavior.Stop);
da.Completed += (S, E) {
//動畫完成,此處表明控件已刷新
};
//啟動動畫觸發(fā)繪制
elememt.BeginAnimation(Control.OpacityProperty, da);
2.使用TaskCompletionSource
使用TaskCompletionSource是為了提供異步接口,方便使用,在使用時只需要await即可。
var tcs = new TaskCompletionSource();
da.Completed += (S, E) => tcs.SetResult();
await tcs.Task;
三、完整代碼
public static class ElementExtensions
{
/// <summary>
/// 等待控件真實刷新后
/// </summary>
internal static Task WaitForPaint(this UIElement elememt)
{
var tcs = new TaskCompletionSource();
//通過動畫來獲取這個時機
var da = new DoubleAnimation(1, 0, new Duration(TimeSpan.FromMilliseconds(1)), FillBehavior.Stop);
da.Completed += (S, E) => tcs.SetResult();
//啟動動畫觸發(fā)繪制
elememt.BeginAnimation(Control.OpacityProperty, da);
return tcs.Task;
}
}
四、使用示例
1、隱藏工具條截屏
private async void Button_Click(object sender, RoutedEventArgs e)
{
//隱藏工具條
toolBar.Visibility= Visibility.Collapsed;
//等待界面上真正隱藏
await toolBar.WaitForPaint();
//截屏
略
//顯示工具條
toolBar.Visibility= Visibility.Visible;
}
2、修改寬高后獲取ActualWidth、ActualHeight
private async void Button_Click(object sender, RoutedEventArgs e)
{
var button = sender as Button;
Console.WriteLine("ActualWidth=" + button.ActualWidth + " ActualHeight=" + button.ActualHeight);
button.Width = 100;
button.Height = 100;
Console.WriteLine("ActualWidth=" + button.ActualWidth + " ActualHeight=" + button.ActualHeight);
await button.WaitForPaint();
Console.WriteLine("ActualWidth=" + button.ActualWidth + " ActualHeight=" + button.ActualHeight);
}
效果預覽文章來源:http://www.zghlxwxcb.cn/news/detail-798173.html
總結(jié)
以上就是今天要講的內(nèi)容,本文的做法是筆者曾經(jīng)在某個論壇看到的建議,然后去嘗試實現(xiàn)發(fā)現(xiàn)是可行的,后來進一步封裝為異步方法。發(fā)出來的主要目的是作為記錄,一方面是方便以后拷貝使用,另一方面也希望能對大家有所幫助。文章來源地址http://www.zghlxwxcb.cn/news/detail-798173.html
到了這里,關于C# wpf 獲取控件刷新的時機的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!