简体   繁体   English

WPF 按钮绑定到属性 Convertback IMultiValueConverter 不会更新值

[英]WPF button binding to a property Convertback IMultiValueConverter does not update value

I have a binding from a toggle button hooked up in code behind.我有一个绑定在后面的代码中的切换按钮。 I want to bind the isChecked state from one button to 4 video controls to toggle the mute function.我想将 isChecked 状态从一个按钮绑定到 4 个视频控件以切换静音功能。 I am using multibinding to bind the toggle button to 4 different controls.我正在使用多重绑定将切换按钮绑定到 4 个不同的控件。 My problem is using breakpoints i can see everything is triggered right up to the property mute property on each object, but the property "value" parameter never gets updated.我的问题是使用断点,我可以看到所有内容都被触发,直到每个对象上的属性静音属性,但属性“值”参数永远不会更新。 It stays at the default setting when the controls are instantiated.当控件被实例化时,它保持默认设置。

So first i create the bindings in code behind所以首先我在后面的代码中创建绑定

        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);

This all seems to work because when i click on the button i can see in the multivalue converter the correct isChecked button status arrives at the breakpoints, at ConvertBack below i can confirm the value is the correct bool that reflects the toggle button state.这一切似乎都有效,因为当我单击按钮时,我可以在多值转换器中看到正确的 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
}

At this point i can confirm it hits the Mute property, and triggers the SET 4 times, but as i trace through it the value parameter remains at the previously set value, and does not update to reflect the value passed to it via ConvertBack在这一点上,我可以确认它击中了 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");
            }

        }
    }

Can anyone help please.任何人都可以请帮忙。 Have been tearing my hair out for 3 days.已经把我的头发撕了 3 天了。

It seemed to me using multibinding is an efficient way to hook up 4 seperat controls players and bind them to one button click.在我看来,使用多重绑定是连接 4 个单独的控件播放器并将它们绑定到一个按钮单击的有效方法。

well I have tried several options again and none of them work except code in a click button event好吧,我再次尝试了几个选项,但除了单击按钮事件中的代码外,它们都不起作用

Multibinding just does not work at all.多重绑定根本不起作用。 I can see in break points that the Mute property is being called 4 times for 4 controls but the value parameter is never updated to the new property value.我可以在断点中看到 Mute 属性被 4 个控件调用 4 次,但 value 参数永远不会更新为新的属性值。

I also tried binding the one button to 4 different controls我还尝试将一个按钮绑定到 4 个不同的控件

foreach(Player player in lsPlayers)
{
    btnMuteToggle.SetBinding(SimpleButton.IsCheckedProperty, new Binding("Mute")
       {
         Source = player,
         UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
         Mode = BindingMode.OneWayToSource
        });
}

This just results in one player object mute property being called.这只会导致调用一个播放器对象静音属性。 You cant bind more than one control to the same button.您不能将多个控件绑定到同一个按钮。 It just does not work.它只是行不通。

so I just called the 4 objects in a click event.所以我只是在点击事件中调用了 4 个对象。

I believe that in this case you may want to bind those 4 properties to the mute property individually and make sure each is set Mode to TwoWay.我相信在这种情况下,您可能希望将这 4 个属性单独绑定到静音属性,并确保每个属性都设置为双向。 But if MultiValueConverter supports it, I can't particularly argue with your approach.但是如果 MultiValueConverter 支持它,我不能特别反对你的方法。

It appears that you have not made a Dependency Property for Mute.看来您还没有为静音创建依赖属性。 this is vital to the WPF Binding Workflow and tends to scale easier than NotifyPropertyChanged as NotifyPropertyChanged can tend towards requiring you to manage more.这对 WPF 绑定工作流至关重要,并且比 NotifyPropertyChanged 更容易扩展,因为 NotifyPropertyChanged 可能会要求您管理更多。 A DependencyProperty will abstract away both sending and receiving the updates to your property and the Xaml editor support for it is better. DependencyProperty 将抽象发送和接收对您的属性的更新,并且 Xaml 编辑器对它的支持更好。

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

I find WPF Binding to be nice in theory, but still requires a lot more leg work than it needs to.我发现 WPF 绑定在理论上很好,但仍然需要比实际需要更多的工作。 Have a function.有一个功能。 I add it to all of my WPF viewmodels and controls.我将它添加到我所有的 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));
}

Just inherit from DependencyObject and you can make mute look more like this:只需从 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); }
}

But Be Warned!但要注意! Sometimes WPF Binding to a Dependency Property updates the Dependency Property's internal values without entering the setter of its corresponding property!有时 WPF 绑定到依赖属性会更新依赖属性的内部值,而无需输入其相应属性的 setter! This was the case on a MultiValueBinding I used.我使用的 MultiValueBinding 就是这种情况。 meaning it may never touch the Mute::Set accessor.这意味着它可能永远不会触及 Mute::Set 访问器。 This can be pretty problematic, to counter this issue you can use the various callbacks available to a DependencyObject!这可能会很成问题,为了解决这个问题,您可以使用 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