[英]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.