2016-11-22 54 views
0

我創建了一個例子來說明我的問題時避免閃爍。如何使用異步綁定

視圖模型:

public class VM : INotifyPropertyChanged 
{ 
    private double _value = 1; 
    public double Value 
    { 
     get { return _value; } 
     set 
     { 
      _value = value; 
      OnPropertyChanged(); 
     } 
    } 

    public VM() 
    { 
     var timer = new DispatcherTimer(); 
     timer.Interval = TimeSpan.FromTicks(1); 
     timer.Tick += (s, e) => { Value += 1; }; 
     timer.Start(); 
    } 

    // OnPropertyChanged stuff ... 
    } 
} 

查看:

<Window.DataContext> 
    <namespace:VM/> 
</Window.DataContext> 
<Grid> 
    <TextBox Text="{Binding Value, IsAsync=True, FallbackValue=Test}"/> 
</Grid> 

當運行我的應用程序中的文本框中的文本閃爍。在更新過程中,會顯示FallbackValue,這對我來說毫無意義。

有誰知道目的或者在更新過程中FallbackValue顯示有什麼好處?有沒有辦法在異步更新過程中顯示舊值?

回答

0

我發現了一種避免閃爍的方法,只是從文本框繼承並覆蓋它的textproperty元數據。

定製TextBoxControl

public class CustomTextBox : TextBox 
{ 
    static CustomTextBox() 
    { 
     TextProperty.OverrideMetadata(typeof(CustomTextBox), new FrameworkPropertyMetadata(null, null, CoerceChanged)); 
    } 

    private static object CoerceChanged(DependencyObject d, object basevalue) 
    { 
     var tb = d as TextBox; 
     if (basevalue == null) 
     { 
      return tb.Text; 
     } 
     return basevalue; 
    } 
} 

查看

<Window.DataContext> 
    <namespace:VM/> 
</Window.DataContext> 
<Grid> 
    <namespace:CustomTextBox Text="{Binding Value, IsAsync=True}"/> 
</Grid> 

有文字結合沒有一個fallbackvalue是很重要的。因此,在更新過程中,文本被設置爲文本屬性defalut值 - 因此在這種情況下爲null

CoerceChanged處理程序檢查新值是否爲空。如果是這樣,他會返回舊值,以便在更新過程中仍顯示舊值。

+0

一個有趣的解決方案..雖然我不認爲這是正確的說你在這裏重寫..它更像是註冊你的派生類型(配置概念)與處理程序..你也可以把一個解析器模式。如果你在調用'TextProperty.OverrideMetadata'的時候輸入了'typeof(TextBox)',它會不會調用處理程序並提供相同的結果?如果你同時指定了'typeof(CustomTextBox)'和'typeof(TextBox)處理程序會觸發兩次嗎? –

+0

@BrettCaswell,不可能使用'typeof(TextBox)' - 你會得到一個異常。因爲已經爲textbox textproperty註冊了元數據。 – ManDani

0

有時綁定會失敗,失敗是重要的考慮因素。如果發生錯誤,則回退值選項向用戶顯示消息,而不是什麼都沒有發生。如果你想你的fallbackvalue顯示包含於前值,我能想到的嘗試幾種方法:在參考字符串值可能保存和/或其他控件,然後綁定到控制

但是,如果你不希望顯示fallbackvalue,你需要做一個代碼檢查,看看你的綁定失敗或緩慢,並將其包含在你的代碼中

+0

他的綁定不​​失敗。它只是顯示回退值,直到屬性獲取器返回。 –

+0

@Peter,這就是我如何瞭解後備值是什麼,但我編輯了我的答案,其中包括響應緩慢 – JohnChris

+0

@ManDani,我會去找Peters解決方案,但是如果您想堅持自己的方式並嘗試,請嘗試綁定將Fallback值保存到隱藏控件中,保存顯示的前一個值的字符串 – JohnChris

1

這對我來說似乎很正常,因爲你是在你的綁定中使用IsAsync=True。從the documentation

在等待值到達,結合報告FallbackValue,如果可用

PropertyChanged事件引發,WPF啓動更新的目標的過程捆綁。通常這會同步發生,立即調用屬性getter來更新值。

但是您使用的是IsAysnc=True,所以WPF使用回退值填充目標,然後啓動異步請求以稍後檢索實際屬性值。在該請求完成之前,會顯示故障預置值。

有沒有人知道在更新過程中顯示FallbackValue的目的或有什麼好處?

根據文檔,IsAsync=True設置背後的意圖是當屬性獲取器的速度慢或可能慢時使用。您的代碼告訴WPF該屬性值已更改,因此它知道舊值不再有效。你的代碼也告訴(通過XAML中的IsAsync)屬性獲取器可能需要一些時間來提供新值,所以它推遲檢索該值直到以後。

同時,WPF應該展示什麼?這就是後備價值所在。

有沒有辦法在異步更新過程中顯示舊值?

如果您不希望爲WPF中的此功能設計的行爲,您應該自己異步檢索新數據,並在您擁有它時通過setter更新屬性。無論如何,一個屬性獲取者的速度並不是一個好主意,所以無論如何這都是一個更好的設計。

+0

我同意這一點。雖然在我的情況下,我沒有一個緩慢的吸氣。正如你所看到的,顯示的值變化非常快。在我的真實應用程序中有幾個文本框 - 所以視圖需要很多時間。通過設置IsAsnyc = True,我試圖避免凍結的視圖。所以在我的情況下,顯示FallbackValue是沒有意義的 - 這隻會導致閃爍。 – ManDani

+1

_「在我的情況下,我沒有緩慢的吸氣劑」_ - 那麼你使用IsAsync = True的動機是什麼?什麼「凍結的看法」發生,爲什麼? WPF可以輕鬆顯示任何合理數量的文本框和其他控件,而不會有明顯的滯後;當你有足夠的屏幕控制來減慢速度時,用戶無論如何都無法理解。這對我來說聽起來像是你真正的問題不應該是關於'IsAsync'(你可能不應該使用它),而應該是關於改善你的真實世界場景的用戶體驗。 –