У меня есть мультисвязь, которая выглядит примерно так:
<UserControl.Visibility>
<MultiBinding Converter="{StaticResource isMouseOverToVisibiltyConverter}">
<Binding ElementName="otherElement" Path="IsMouseOver" />
<Binding RelativeSource="{RelativeSource Self}" Path="IsMouseOver" />
</MultiBinding>
</UserControl.Visibility>
И я хочу иметь возможность добавить задержку между IsMouseOver, равным false для обеих привязок, и значением Visibility, установленным на Collapsed.
Я нашел эту реализацию DelayBinding: http://www.paulstovell.com/wpf-delaybinding
Но это не работает для MultiBinding, и я не смог выяснить, как создать такую, которая работает с MultiBinding.
У меня есть возможность вносить изменения в Visibility в событиях в выделенном фрагменте кода, и это будет работать, но было бы неплохо, если бы был какой-то способ сделать это через систему привязки.
Есть ли способ добавить задержку для MultiBinding?
РЕДАКТИРОВАТЬ: Рэй, чтобы заставить ваш класс компилироваться и запускаться, мне пришлось внести некоторые исправления.Однако, что-то все еще не так, поскольку обновления не распространяются.Похоже, что свойство цели обновляется только один раз.
[ContentProperty("Bindings")]
public class DelayedMultiBindingExtension : MarkupExtension, IMultiValueConverter, INotifyPropertyChanged
{
public Collection<BindingBase> Bindings { get; private set; }
public IMultiValueConverter Converter { get; set; }
public object ConverterParameter { get; set; }
public CultureInfo ConverterCulture { get; set; }
public BindingMode Mode { get; set; }
public UpdateSourceTrigger UpdateSourceTrigger { get; set; }
public object CurrentValue { get { return _delayedValue; } set { _delayedValue = _undelayedValue = value; _timer.Stop(); } }
private object _undelayedValue;
private object _delayedValue;
private DispatcherTimer _timer;
public int ChangeCount { get; private set; } // Public so Binding can bind to it
public DelayedMultiBindingExtension()
{
this.Bindings = new Collection<BindingBase>();
_timer = new DispatcherTimer();
_timer.Tick += _timer_Tick;
_timer.Interval = TimeSpan.FromMilliseconds(500);
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
var valueProvider = serviceProvider.GetService(typeof(IProvideValueTarget)) as IProvideValueTarget;
if (valueProvider != null)
{
var bindingTarget = valueProvider.TargetObject as DependencyObject;
var bindingProperty = valueProvider.TargetProperty as DependencyProperty;
var multi = new MultiBinding { Converter = this, Mode = Mode, UpdateSourceTrigger = UpdateSourceTrigger };
foreach (var binding in Bindings)
multi.Bindings.Add(binding);
multi.Bindings.Add(new Binding("ChangeCount") { Source = this, Mode = BindingMode.OneWay });
var bindingExpression = BindingOperations.SetBinding(bindingTarget, bindingProperty, multi);
return bindingTarget.GetValue(bindingProperty);
}
return null;
}
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
object newValue =
Converter.Convert(
values.Take(values.Length - 1).ToArray(),
targetType,
ConverterParameter,
ConverterCulture ?? culture);
if (!object.Equals(newValue, _undelayedValue))
{
_undelayedValue = newValue;
_timer.Stop();
_timer.Start();
}
return _delayedValue;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
return
Converter.ConvertBack(value, targetTypes, ConverterParameter, ConverterCulture ?? culture)
.Concat(new object[] { ChangeCount }).ToArray();
}
private void _timer_Tick(object sender, EventArgs e)
{
_timer.Stop();
_delayedValue = _undelayedValue;
ChangeCount++;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("ChangeCount"));
}
public event PropertyChangedEventHandler PropertyChanged;
}
EDIT2: Несмотря на то, что я не смог заставить работать код Рэя, я пометил его как ответ, потому что это привело меня к некоторому коду, которыйРабота.Смотрите мой ответ ниже для кода, который я использовал.