簡體   English   中英

WPF 按鈕綁定到屬性 Convertback IMultiValueConverter 不會更新值

[英]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 編輯器對它的支持更好。

https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/how-to-implement-a-dependency-property

我發現 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM