Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# .Net 4.0中.Net 4.5绑定的延迟属性_C#_Wpf_Binding_.net 4.0_.net 4.5 - Fatal编程技术网

C# .Net 4.0中.Net 4.5绑定的延迟属性

C# .Net 4.0中.Net 4.5绑定的延迟属性,c#,wpf,binding,.net-4.0,.net-4.5,C#,Wpf,Binding,.net 4.0,.net 4.5,如何在.Net 4.0中的绑定上实现.Net 4.5(已描述)中的延迟属性 我知道我不能从BindingBase继承,因为ProvideValue是密封的 我可以实现MarkupExtension,但这意味着我现在必须从BindingExtension重写所有属性。还有其他方法吗?我将创建一个指定延迟时间的AttachedProperty。AttachedProperty将在绑定值更改时启动(或重置)计时器,并在达到指定的时间量时手动更新绑定源 您可以使用以下命令更新源绑定: BindingOp

如何在.Net 4.0中的绑定上实现.Net 4.5(已描述)中的延迟属性

我知道我不能从BindingBase继承,因为ProvideValue是密封的


我可以实现MarkupExtension,但这意味着我现在必须从BindingExtension重写所有属性。还有其他方法吗?

我将创建一个指定延迟时间的
AttachedProperty
AttachedProperty
将在绑定值更改时启动(或重置)计时器,并在达到指定的时间量时手动更新绑定源

您可以使用以下命令更新源绑定:

BindingOperations.GetBindingExpressionBase(
    dependencyObject, dependencyProperty).UpdateSource();
编辑


我今天正在修复一些旧代码中的一个bug,注意到它使用附加的行为实现了延迟的属性更改通知。我想到了这个问题,所以按照我在代码中注释过的链接,发现自己遇到了一个问题,我不久前在Soabout上发布了这个问题。最重要的答案是我目前实现的一个,它是一些附加属性,在X毫秒过去后更新绑定的源。

直接移植是不可能的,但是我们可以使用
多绑定来“模拟”它吗

请注意,这是一个非常紧密耦合的解决方案,如果在一个页面上使用了许多这样的绑定,那么可能无法很好地执行

两个必须有一个

  • 它接受单个项目
    ArrayList
    中以毫秒为单位的延迟作为转换器参数
  • 每个这样的延迟绑定都必须携带自己的转换器参数实例
  • 测试XAML如下所示

        <TextBlock xmlns:Collections="clr-namespace:System.Collections;assembly=mscorlib"
                   xmlns:System="clr-namespace:System;assembly=mscorlib" >
            <TextBlock.Resources>
                <local:DelayHelper x:Key="DelayHelper"/>
                <Collections:ArrayList x:Key="MultiConverterParameter">
                    <System:Int32>2000</System:Int32>
                </Collections:ArrayList>
            </TextBlock.Resources>
            <TextBlock.Text>
                <MultiBinding UpdateSourceTrigger="LostFocus"
                     Converter="{StaticResource DelayHelper}"
                     ConverterParameter="{StaticResource MultiConverterParameter}">
                    <Binding Path="Text" ElementName="MyTextBox" Mode="OneWay" />
                    <Binding RelativeSource="{RelativeSource Self}"/>                    
                    <Binding BindsDirectlyToSource="True"
                             Source="{x:Static TextBlock.TextProperty}"/>
                </MultiBinding>
            </TextBlock.Text>
        </TextBlock>
    
        <TextBox x:Name="MyTextBox" Text="Test..."/>
    
    所以这段代码利用了

  • 多重绑定可以接受目标UI元素(
    TextBlock
    )及其本身是多重绑定的依赖属性(
    TextBlock.TextProperty
  • 绑定后,多重绑定无法更改其属性,包括
    converterParameter
    。但是转换器参数本身可以是一个引用对象,在整个绑定过程中保持其引用处于活动状态,例如
    ArrayList
  • 调度程序在第一次勾选
    后必须停止。因此,我们使用
    temp
    变量是非常必要的
  • 更新为每个源文本更新进行2次转换器传递。这种行为没有escpae。如果使用了许多延迟绑定,这可能会导致速度缓慢
  • 确保在多个延迟绑定之间不共享相同的转换器参数

  • 让我知道这是否有帮助…

    最后,我决定使用composition实现DelayedBinding作为MarkupExtension

    我遇到的唯一问题是,如果
    IProvideValueTarget
    中的
    TargetProperty
    为空,则DataTemplates
    ProvideValue
    应返回此值

    [MarkupExtensionReturnType(typeof(object))]
    public class DelayedBindingExtension : MarkupExtension
    {
        private readonly Binding _binding = new Binding();
    
        public DelayedBindingExtension()
        {
            //Default value for delay
            Delay = TimeSpan.FromSeconds(0.5);
        }
    
        public DelayedBindingExtension(PropertyPath path)
            : this()
        {
            Path = path;
        }
    
        #region properties
    
        [DefaultValue(null)]
        public object AsyncState
        {
            get { return _binding.AsyncState; }
            set { _binding.AsyncState = value; }
        }
    
        [DefaultValue(false)]
        public bool BindsDirectlyToSource
        {
            get { return _binding.BindsDirectlyToSource; }
            set { _binding.BindsDirectlyToSource = value; }
        }
    
        [DefaultValue(null)]
        public IValueConverter Converter
        {
            get { return _binding.Converter; }
            set { _binding.Converter = value; }
        }
    
        [TypeConverter(typeof(CultureInfoIetfLanguageTagConverter)), DefaultValue(null)]
        public CultureInfo ConverterCulture
        {
            get { return _binding.ConverterCulture; }
            set { _binding.ConverterCulture = value; }
        }
    
        [DefaultValue(null)]
        public object ConverterParameter
        {
            get { return _binding.ConverterParameter; }
            set { _binding.ConverterParameter = value; }
        }
    
        [DefaultValue(null)]
        public string ElementName
        {
            get { return _binding.ElementName; }
            set { _binding.ElementName = value; }
        }
    
        [DefaultValue(null)]
        public object FallbackValue
        {
            get { return _binding.FallbackValue; }
            set { _binding.FallbackValue = value; }
        }
    
        [DefaultValue(false)]
        public bool IsAsync
        {
            get { return _binding.IsAsync; }
            set { _binding.IsAsync = value; }
        }
    
        [DefaultValue(BindingMode.Default)]
        public BindingMode Mode
        {
            get { return _binding.Mode; }
            set { _binding.Mode = value; }
        }
    
        [DefaultValue(false)]
        public bool NotifyOnSourceUpdated
        {
            get { return _binding.NotifyOnSourceUpdated; }
            set { _binding.NotifyOnSourceUpdated = value; }
        }
    
        [DefaultValue(false)]
        public bool NotifyOnTargetUpdated
        {
            get { return _binding.NotifyOnTargetUpdated; }
            set { _binding.NotifyOnTargetUpdated = value; }
        }
    
        [DefaultValue(false)]
        public bool NotifyOnValidationError
        {
            get { return _binding.NotifyOnValidationError; }
            set { _binding.NotifyOnValidationError = value; }
        }
    
        [DefaultValue(null)]
        public PropertyPath Path
        {
            get { return _binding.Path; }
            set { _binding.Path = value; }
        }
    
        [DefaultValue(null)]
        public RelativeSource RelativeSource
        {
            get { return _binding.RelativeSource; }
            set { _binding.RelativeSource = value; }
        }
    
        [DefaultValue(null)]
        public object Source
        {
            get { return _binding.Source; }
            set { _binding.Source = value; }
        }
    
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public UpdateSourceExceptionFilterCallback UpdateSourceExceptionFilter
        {
            get { return _binding.UpdateSourceExceptionFilter; }
            set { _binding.UpdateSourceExceptionFilter = value; }
        }
    
        [DefaultValue(UpdateSourceTrigger.Default)]
        public UpdateSourceTrigger UpdateSourceTrigger
        {
            get { return _binding.UpdateSourceTrigger; }
            set { _binding.UpdateSourceTrigger = value; }
        }
    
        [DefaultValue(null)]
        public object TargetNullValue
        {
            get { return _binding.TargetNullValue; }
            set { _binding.TargetNullValue = value; }
        }
    
        [DefaultValue(null)]
        public string StringFormat
        {
            get { return _binding.StringFormat; }
            set { _binding.StringFormat = value; }
        }
    
        [DefaultValue(false)]
        public bool ValidatesOnDataErrors
        {
            get { return _binding.ValidatesOnDataErrors; }
            set { _binding.ValidatesOnDataErrors = value; }
        }
    
        [DefaultValue(false)]
        public bool ValidatesOnExceptions
        {
            get { return _binding.ValidatesOnExceptions; }
            set { _binding.ValidatesOnExceptions = value; }
        }
    
        [DefaultValue(null)]
        public string XPath
        {
            get { return _binding.XPath; }
            set { _binding.XPath = value; }
        }
    
        [DefaultValue(null)]
        public Collection<ValidationRule> ValidationRules
        {
            get { return _binding.ValidationRules; }
        }
    
        #endregion
    
        [DefaultValue(null)]
        public TimeSpan Delay { get; set; }
    
        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            try
            {
                _binding.Mode = BindingMode.TwoWay;
                _binding.UpdateSourceTrigger = UpdateSourceTrigger.Explicit;
            }
            catch (InvalidOperationException)  //Binding in use already don't change it
            {
            }
    
            var valueProvider = serviceProvider.GetService(typeof (IProvideValueTarget)) as IProvideValueTarget;
            if (valueProvider != null)
            {
                var bindingTarget = valueProvider.TargetObject as DependencyObject;
                var bindingProperty = valueProvider.TargetProperty as DependencyProperty;
                if (bindingProperty != null && bindingTarget != null)
                {
                    var result = (BindingExpression)_binding.ProvideValue(serviceProvider);
    
                    new DelayBindingManager(result, bindingTarget, bindingProperty, Delay);
                    return result;
                }
            }
    
            return this;
        }
    
        private class DelayBindingManager
        {
            private readonly BindingExpressionBase _bindingExpression;
            private readonly DependencyProperty _bindingTargetProperty;
            private DependencyPropertyDescriptor _descriptor;
            private readonly DispatcherTimer _timer;
    
            public DelayBindingManager(BindingExpressionBase bindingExpression, DependencyObject bindingTarget, DependencyProperty bindingTargetProperty, TimeSpan delay)
            {
                _bindingExpression = bindingExpression;
                _bindingTargetProperty = bindingTargetProperty;
    
                _descriptor = DependencyPropertyDescriptor.FromProperty(_bindingTargetProperty, bindingTarget.GetType());
                if (_descriptor != null)
                    _descriptor.AddValueChanged(bindingTarget, BindingTargetTargetPropertyChanged);
    
                _timer = new DispatcherTimer();
                _timer.Tick += TimerTick;
                _timer.Interval = delay;
            }
    
            private void BindingTargetTargetPropertyChanged(object sender, EventArgs e)
            {
                var source = (DependencyObject)sender;
                if (!BindingOperations.IsDataBound(source, _bindingTargetProperty))
                {
                    if (_descriptor != null)
                    {
                        _descriptor.RemoveValueChanged(source, BindingTargetTargetPropertyChanged);
                        _descriptor = null;
                    }
                    return;
                }
    
                _timer.Stop();
                _timer.Start();
            }
    
            private void TimerTick(object sender, EventArgs e)
            {
                _timer.Stop();
                _bindingExpression.UpdateSource();
            }
        }
    }
    
    [MarkupExtensionReturnType(typeof(object))]
    公共类DelayedBindingExtension:MarkupExtension
    {
    私有只读绑定_Binding=新绑定();
    公共DelayedBindingExtension()
    {
    //延迟的默认值
    延迟=从秒开始的时间跨度(0.5);
    }
    公共DelayedBindingExtension(PropertyPath路径)
    :此()
    {
    路径=路径;
    }
    #区域属性
    [默认值(空)]
    公共对象异步状态
    {
    获取{return\u binding.AsyncState;}
    设置{u binding.AsyncState=value;}
    }
    [默认值(false)]
    公共bool BindsDirectlyToSource
    {
    获取{return\u binding.BindsDirectlyToSource;}
    设置{u binding.BindsDirectlyToSource=value;}
    }
    [默认值(空)]
    公用变频器
    {
    获取{return\u binding.Converter;}
    设置{u binding.Converter=value;}
    }
    [TypeConverter(typeof(CultureInfoietFlangGetAgConverter)),默认值(null)]
    公共文化信息转换器文化
    {
    获取{return\u binding.ConverterCulture;}
    设置{u binding.ConverterCulture=value;}
    }
    [默认值(空)]
    公共对象转换器参数
    {
    获取{return\u binding.ConverterParameter;}
    设置{u binding.ConverterParameter=value;}
    }
    [默认值(空)]
    公共字符串元素名
    {
    获取{return\u binding.ElementName;}
    设置{u binding.ElementName=value;}
    }
    [默认值(空)]
    公共对象回退值
    {
    获取{return\u binding.FallbackValue;}
    设置{u binding.FallbackValue=value;}
    }
    [默认值(false)]
    公共广播同步
    {
    获取{return\u binding.IsAsync;}
    设置{u binding.IsAsync=value;}
    }
    [默认值(BindingMode.Default)]
    公共绑定模式
    {
    获取{return\u binding.Mode;}
    设置{u binding.Mode=value;}
    }
    [默认值(false)]
    公共bool NotifyOnSourceUpdated
    {
    获取{return\u binding.NotifyOnSourceUpdated;}
    设置{u binding.NotifyOnSourceUpdated=value;}
    }
    [默认值(false)]
    公共布尔NotifyOnTargetUpdated
    {
    获取{return\u binding.NotifyOnTargetUpdated;}
    设置{u binding.NotifyOnTargetUpdated=value;}
    }
    [默认值(false)]
    公共布尔NotifyOnValidationError
    {
    获取{return\u binding.NotifyOnValidationError;}
    设置{u binding.NotifyOnValidationError=value;}
    }
    [默认值(空)]
    公共属性路径
    {
    获取{return\u binding.Path;}
    设置{u binding.Path=value;}
    }
    [默认值(空)]
    公共相对资源相对资源
    {
    获取{return\u binding.RelativeSource;}
    设置{u binding.RelativeSource=value;}
    }
    [默认值(空)]
    公共对象源
    {
    获取{return\u binding.Source;}
    设置{u binding.Source=value;}
    }
    [DesignerSerializationVisibility(DesignerSerializationVisibility.Hi
    
    [MarkupExtensionReturnType(typeof(object))]
    public class DelayedBindingExtension : MarkupExtension
    {
        private readonly Binding _binding = new Binding();
    
        public DelayedBindingExtension()
        {
            //Default value for delay
            Delay = TimeSpan.FromSeconds(0.5);
        }
    
        public DelayedBindingExtension(PropertyPath path)
            : this()
        {
            Path = path;
        }
    
        #region properties
    
        [DefaultValue(null)]
        public object AsyncState
        {
            get { return _binding.AsyncState; }
            set { _binding.AsyncState = value; }
        }
    
        [DefaultValue(false)]
        public bool BindsDirectlyToSource
        {
            get { return _binding.BindsDirectlyToSource; }
            set { _binding.BindsDirectlyToSource = value; }
        }
    
        [DefaultValue(null)]
        public IValueConverter Converter
        {
            get { return _binding.Converter; }
            set { _binding.Converter = value; }
        }
    
        [TypeConverter(typeof(CultureInfoIetfLanguageTagConverter)), DefaultValue(null)]
        public CultureInfo ConverterCulture
        {
            get { return _binding.ConverterCulture; }
            set { _binding.ConverterCulture = value; }
        }
    
        [DefaultValue(null)]
        public object ConverterParameter
        {
            get { return _binding.ConverterParameter; }
            set { _binding.ConverterParameter = value; }
        }
    
        [DefaultValue(null)]
        public string ElementName
        {
            get { return _binding.ElementName; }
            set { _binding.ElementName = value; }
        }
    
        [DefaultValue(null)]
        public object FallbackValue
        {
            get { return _binding.FallbackValue; }
            set { _binding.FallbackValue = value; }
        }
    
        [DefaultValue(false)]
        public bool IsAsync
        {
            get { return _binding.IsAsync; }
            set { _binding.IsAsync = value; }
        }
    
        [DefaultValue(BindingMode.Default)]
        public BindingMode Mode
        {
            get { return _binding.Mode; }
            set { _binding.Mode = value; }
        }
    
        [DefaultValue(false)]
        public bool NotifyOnSourceUpdated
        {
            get { return _binding.NotifyOnSourceUpdated; }
            set { _binding.NotifyOnSourceUpdated = value; }
        }
    
        [DefaultValue(false)]
        public bool NotifyOnTargetUpdated
        {
            get { return _binding.NotifyOnTargetUpdated; }
            set { _binding.NotifyOnTargetUpdated = value; }
        }
    
        [DefaultValue(false)]
        public bool NotifyOnValidationError
        {
            get { return _binding.NotifyOnValidationError; }
            set { _binding.NotifyOnValidationError = value; }
        }
    
        [DefaultValue(null)]
        public PropertyPath Path
        {
            get { return _binding.Path; }
            set { _binding.Path = value; }
        }
    
        [DefaultValue(null)]
        public RelativeSource RelativeSource
        {
            get { return _binding.RelativeSource; }
            set { _binding.RelativeSource = value; }
        }
    
        [DefaultValue(null)]
        public object Source
        {
            get { return _binding.Source; }
            set { _binding.Source = value; }
        }
    
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public UpdateSourceExceptionFilterCallback UpdateSourceExceptionFilter
        {
            get { return _binding.UpdateSourceExceptionFilter; }
            set { _binding.UpdateSourceExceptionFilter = value; }
        }
    
        [DefaultValue(UpdateSourceTrigger.Default)]
        public UpdateSourceTrigger UpdateSourceTrigger
        {
            get { return _binding.UpdateSourceTrigger; }
            set { _binding.UpdateSourceTrigger = value; }
        }
    
        [DefaultValue(null)]
        public object TargetNullValue
        {
            get { return _binding.TargetNullValue; }
            set { _binding.TargetNullValue = value; }
        }
    
        [DefaultValue(null)]
        public string StringFormat
        {
            get { return _binding.StringFormat; }
            set { _binding.StringFormat = value; }
        }
    
        [DefaultValue(false)]
        public bool ValidatesOnDataErrors
        {
            get { return _binding.ValidatesOnDataErrors; }
            set { _binding.ValidatesOnDataErrors = value; }
        }
    
        [DefaultValue(false)]
        public bool ValidatesOnExceptions
        {
            get { return _binding.ValidatesOnExceptions; }
            set { _binding.ValidatesOnExceptions = value; }
        }
    
        [DefaultValue(null)]
        public string XPath
        {
            get { return _binding.XPath; }
            set { _binding.XPath = value; }
        }
    
        [DefaultValue(null)]
        public Collection<ValidationRule> ValidationRules
        {
            get { return _binding.ValidationRules; }
        }
    
        #endregion
    
        [DefaultValue(null)]
        public TimeSpan Delay { get; set; }
    
        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            try
            {
                _binding.Mode = BindingMode.TwoWay;
                _binding.UpdateSourceTrigger = UpdateSourceTrigger.Explicit;
            }
            catch (InvalidOperationException)  //Binding in use already don't change it
            {
            }
    
            var valueProvider = serviceProvider.GetService(typeof (IProvideValueTarget)) as IProvideValueTarget;
            if (valueProvider != null)
            {
                var bindingTarget = valueProvider.TargetObject as DependencyObject;
                var bindingProperty = valueProvider.TargetProperty as DependencyProperty;
                if (bindingProperty != null && bindingTarget != null)
                {
                    var result = (BindingExpression)_binding.ProvideValue(serviceProvider);
    
                    new DelayBindingManager(result, bindingTarget, bindingProperty, Delay);
                    return result;
                }
            }
    
            return this;
        }
    
        private class DelayBindingManager
        {
            private readonly BindingExpressionBase _bindingExpression;
            private readonly DependencyProperty _bindingTargetProperty;
            private DependencyPropertyDescriptor _descriptor;
            private readonly DispatcherTimer _timer;
    
            public DelayBindingManager(BindingExpressionBase bindingExpression, DependencyObject bindingTarget, DependencyProperty bindingTargetProperty, TimeSpan delay)
            {
                _bindingExpression = bindingExpression;
                _bindingTargetProperty = bindingTargetProperty;
    
                _descriptor = DependencyPropertyDescriptor.FromProperty(_bindingTargetProperty, bindingTarget.GetType());
                if (_descriptor != null)
                    _descriptor.AddValueChanged(bindingTarget, BindingTargetTargetPropertyChanged);
    
                _timer = new DispatcherTimer();
                _timer.Tick += TimerTick;
                _timer.Interval = delay;
            }
    
            private void BindingTargetTargetPropertyChanged(object sender, EventArgs e)
            {
                var source = (DependencyObject)sender;
                if (!BindingOperations.IsDataBound(source, _bindingTargetProperty))
                {
                    if (_descriptor != null)
                    {
                        _descriptor.RemoveValueChanged(source, BindingTargetTargetPropertyChanged);
                        _descriptor = null;
                    }
                    return;
                }
    
                _timer.Stop();
                _timer.Start();
            }
    
            private void TimerTick(object sender, EventArgs e)
            {
                _timer.Stop();
                _bindingExpression.UpdateSource();
            }
        }
    }