![](/img/trans.png)
[英]Get the Source value in ConvertBack() method for IValueConverter implementation in WPF binding
[英]WPF button binding to a property Convertback IMultiValueConverter does not update value
我有一個綁定在后面的代碼中的切換按鈕。 我想將 isChecked 狀態從一個按鈕綁定到 4 個視頻控件以切換靜音功能。 我正在使用多重綁定將切換按鈕綁定到 4 個不同的控件。 我的問題是使用斷點,我可以看到所有內容都被觸發,直到每個對象上的屬性靜音屬性,但屬性“值”參數永遠不會更新。 當控件被實例化時,它保持默認設置。
所以首先我在后面的代碼中創建綁定
IMultiValueConverter converter = new EmptyMultiValueConverter();
MultiBinding myMultiBinding = new MultiBinding();
myMultiBinding.Converter = converter;
myMultiBinding.UpdateSourceTrigger = UpdateSourceTrigger.Default;
myMultiBinding.Mode = BindingMode.OneWayToSource;
myMultiBinding.NotifyOnSourceUpdated = true;
for (int i = 1; i < _maxNumberofPlayers; i++)
{
VideoPlayer player = new VideoPlayer()
{
Mute = false
};
myMultiBinding.Bindings.Add(new Binding("Mute") { Source = player
});
}
btnMuteToggle.SetBinding(SimpleButton.IsCheckedProperty, myMultiBinding);
這一切似乎都有效,因為當我單擊按鈕時,我可以在多值轉換器中看到正確的 isChecked 按鈕狀態到達斷點,在下面的 ConvertBack 中,我可以確認該值是反映切換按鈕狀態的正確布爾值。
public class EmptyMultiValueConverter : IMultiValueConverter
{
#region IMultiValueConverter Members
public object Convert(object[] values, Type targetType, object
parameter, System.Globalization.CultureInfo culture)
{
// gets from the object source
return (bool)values[0];
}
public object[] ConvertBack(object value, Type[] targetTypes, object
parameter, System.Globalization.CultureInfo culture)
{
return new Object[] {value,value,value,value};
}
#endregion
}
在這一點上,我可以確認它擊中了 Mute 屬性,並觸發了 SET 4 次,但是當我跟蹤它時,value 參數保持在先前設置的值,並且不會更新以反映通過 ConvertBack 傳遞給它的值
// mute property in the media player user control
public bool Mute
{
get { return _media.IsMuted; }
set
{
if (_media.IsMuted == value)
return;
else
{
_media.IsMuted = value;
NotifyPropertyChanged("Mute");
}
}
}
任何人都可以請幫忙。 已經把我的頭發撕了 3 天了。
在我看來,使用多重綁定是連接 4 個單獨的控件播放器並將它們綁定到一個按鈕單擊的有效方法。
好吧,我再次嘗試了幾個選項,但除了單擊按鈕事件中的代碼外,它們都不起作用
多重綁定根本不起作用。 我可以在斷點中看到 Mute 屬性被 4 個控件調用 4 次,但 value 參數永遠不會更新為新的屬性值。
我還嘗試將一個按鈕綁定到 4 個不同的控件
foreach(Player player in lsPlayers)
{
btnMuteToggle.SetBinding(SimpleButton.IsCheckedProperty, new Binding("Mute")
{
Source = player,
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
Mode = BindingMode.OneWayToSource
});
}
這只會導致調用一個播放器對象靜音屬性。 您不能將多個控件綁定到同一個按鈕。 它只是行不通。
所以我只是在點擊事件中調用了 4 個對象。
我相信在這種情況下,您可能希望將這 4 個屬性單獨綁定到靜音屬性,並確保每個屬性都設置為雙向。 但是如果 MultiValueConverter 支持它,我不能特別反對你的方法。
看來您還沒有為靜音創建依賴屬性。 這對 WPF 綁定工作流至關重要,並且比 NotifyPropertyChanged 更容易擴展,因為 NotifyPropertyChanged 可能會要求您管理更多。 DependencyProperty 將抽象發送和接收對您的屬性的更新,並且 Xaml 編輯器對它的支持更好。
我發現 WPF 綁定在理論上很好,但仍然需要比實際需要更多的工作。 有一個功能。 我將它添加到我所有的 WPF 視圖模型和控件中。
/// <summary>
/// simplify wpf binding
/// </summary>
/// <param name="name"></param>
/// <param name="type"></param>
/// <param name="preferNull">Fair Warning. if you create an instance, you will have also created a singleton of this property for all instances of this class. </param>
/// <returns></returns>
private static DependencyProperty AddDp(string name, Type type, bool preferNull = true)
{
return DependencyProperty.Register(name, type, typeof(Setting),
new PropertyMetadata((!preferNull || type.IsValueType) ? Activator.CreateInstance(type) : null));
}
只需從 DependencyObject 繼承,您就可以使靜音看起來更像這樣:
public static readonly DependencyProperty MuteDp = AddDp(nameof(Mute), typeof(bool));
public bool Mute
{
get => (bool)GetValue(MuteDp);
set { if(value != Mute) SetValue(MuteDp, value); }
}
但要注意! 有時 WPF 綁定到依賴屬性會更新依賴屬性的內部值,而無需輸入其相應屬性的 setter! 我使用的 MultiValueBinding 就是這種情況。 這意味着它可能永遠不會觸及 Mute::Set 訪問器。 這可能會很成問題,為了解決這個問題,您可以使用 DependencyObject 可用的各種回調!
private static DependencyProperty AddDp(string name, Type type, bool preferNull = true)
{
var dp = DependencyProperty.Register(name, type, typeof(Setting),
new PropertyMetadata(
(!preferNull || type.IsValueType) ? Activator.CreateInstance(type) : null
,new PropertyChangedCallback((dobj, dpe)=>
{
//after property changed.
//forcing usage of set accessor
((MuteContainerObj)dobj).Value = ((strong text)dobj).Value;
//or forcibly use an update function
((MuteContainerObj)dobj).MuteUpdated();
}),new CoerceValueCallback((dobj, o)=> {
//before property changed
return o;
})), new ValidateValueCallback((o)=> {
//before property change events
return true;
}));
return dp;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.