【问题标题】:WPF button binding to a property Convertback IMultiValueConverter does not update valueWPF 按钮绑定到属性 Convertback IMultiValueConverter 不更新值
【发布时间】:2019-08-05 11:22:54
【问题描述】:

我有一个绑定在后面代码中的切换按钮。 我想将 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 参数保持在先前设置的值,并且不会更新以反映通过它传递给它的值转换返回

   // 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 个独立控件播放器并将它们绑定到一个按钮单击的有效方法。

【问题讨论】:

  • 我已经读了 3 遍了,我不明白你在一般情况下要做什么......
  • 我试图让多重绑定工作以单击一个切换按钮并使用 ischecked(true 或 false)状态绑定到 4 个不同的媒体播放器控件并在这些控件上切换静音状态属性。跨度>
  • 如果您有 4 个媒体控件并希望通过一个按钮将它们全部静音,则无需多重绑定,只需将它们全部绑定到按钮即可,无需转换器
  • 我在后面的代码中尝试了这一点,方法是为同一个切换按钮创建 4 个单独的绑定实例。但唯一起作用的是最后一个绑定。否则,在后面的代码中将一个按钮绑定到一个视频控件效果很好。
  • 有道理!您仍然可以将所有这些控件绑定到同一个切换按钮。这里不需要多重绑定,也不需要转换器。如果这一切让您发疯,您仍然可以在按下切换按钮时使用 icommand 将它们静音和取消静音。这也将使您能够恢复他们之前的状态。示例:全部静音,但只有一个->单击->全部静音->单击->全部未静音->4个媒体播放器发出声音,而不是只有一个那是以前

标签: c# wpf binding converters multibinding


【解决方案1】:

好吧,我再次尝试了几个选项,但除了单击按钮事件中的代码外,它们都不起作用

多重绑定根本不起作用。 我可以在断点中看到,4 个控件的 Mute 属性被调用了 4 次,但 value 参数从未更新为新的属性值。

我还尝试将一个按钮绑定到 4 个不同的控件

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

这只会导致调用一个播放器对象的静音属性。 您不能将多个控件绑定到同一个按钮。 它只是不起作用。

所以我只是在点击事件中调用了 4 个对象。

【讨论】:

    【解决方案2】:

    我相信在这种情况下,您可能希望将这 4 个属性分别绑定到 mute 属性,并确保将每个属性都设置为 TwoWay。但是如果 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 绑定到依赖属性会更新依赖属性的内部值,而无需输入其相应属性的设置器!我使用的 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;
            
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-02-03
      • 2014-04-28
      • 1970-01-01
      相关资源
      最近更新 更多