[WPF系列]-DataBinding(数据绑定) 自定义Binding
自定义Binding
A base class for custom WPF binding markup extensions
BindingDecoratorBase
Code:
public class LookupExtension : BindingDecoratorBase { //A property that can be set in XAML public string LookupKey { get; set; } public override object ProvideValue(IServiceProvider provider) { //delegate binding creation etc. to the base class object val = base.ProvideValue(provider); //try to get bound items for our custom work DependencyObject targetObject; DependencyProperty targetProperty; bool status = TryGetTargetItems(provider, out targetObject, out targetProperty); if (status) { //associate an input listener with the control InputHandler.RegisterHandler(targetObject, LookupKey); } return val; } }
XAML:
<TextBox Name="txtZipCode"> <TextBox.Text> <local:LookupExtension Source="{StaticResource MyAddress}" Path="ZipCode" LookupKey="F5" /> </TextBox.Text> </TextBox>
效果图:
---------------------------------------------===================================------------------------------
DelayBinding: a custom WPF Binding
<TextBox Text="{z:DelayBinding Path=SearchText, Delay='00:00:01'}" />
[MarkupExtensionReturnType(typeof(object))] public class DelayBindingExtension : MarkupExtension { public DelayBindingExtension() { Delay = TimeSpan.FromSeconds(0.5); } public DelayBindingExtension(PropertyPath path) : this() { Path = path; } public IValueConverter Converter { get; set; } public object ConverterParamter { get; set; } public string ElementName { get; set; } public RelativeSource RelativeSource { get; set; } public object Source { get; set; } public bool ValidatesOnDataErrors { get; set; } public bool ValidatesOnExceptions { get; set; } public TimeSpan Delay { get; set; } [ConstructorArgument("path")] public PropertyPath Path { get; set; } [TypeConverter(typeof(CultureInfoIetfLanguageTagConverter))] public CultureInfo ConverterCulture { get; set; } 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; if (bindingProperty == null || bindingTarget == null) { throw new NotSupportedException(string.Format( "The property '{0}' on target '{1}' is not valid for a DelayBinding. The DelayBinding target must be a DependencyObject, " + "and the target property must be a DependencyProperty.", valueProvider.TargetProperty, valueProvider.TargetObject)); } var binding = new Binding(); binding.Path = Path; binding.Converter = Converter; binding.ConverterCulture = ConverterCulture; binding.ConverterParameter = ConverterParamter; if (ElementName != null) binding.ElementName = ElementName; if (RelativeSource != null) binding.RelativeSource = RelativeSource; if (Source != null) binding.Source = Source; binding.ValidatesOnDataErrors = ValidatesOnDataErrors; binding.ValidatesOnExceptions = ValidatesOnExceptions; return DelayBinding.SetBinding(bindingTarget, bindingProperty, Delay, binding); } return null; } }
public class DelayBinding { private readonly BindingExpressionBase _bindingExpression; private readonly DispatcherTimer _timer; protected DelayBinding(BindingExpressionBase bindingExpression, DependencyObject bindingTarget, DependencyProperty bindingTargetProperty, TimeSpan delay) { _bindingExpression = bindingExpression; // Subscribe to notifications for when the target property changes. This event handler will be // invoked when the user types, clicks, or anything else which changes the target property var descriptor = DependencyPropertyDescriptor.FromProperty(bindingTargetProperty, bindingTarget.GetType()); descriptor.AddValueChanged(bindingTarget, BindingTarget_TargetPropertyChanged); // Add support so that the Enter key causes an immediate commit var frameworkElement = bindingTarget as FrameworkElement; if (frameworkElement != null) { frameworkElement.KeyUp += BindingTarget_KeyUp; } // Setup the timer, but it won't be started until changes are detected _timer = new DispatcherTimer(); _timer.Tick += Timer_Tick; _timer.Interval = delay; } private void BindingTarget_KeyUp(object sender, KeyEventArgs e) { if (e.Key != Key.Enter) return; _timer.Stop(); _bindingExpression.UpdateSource(); } private void BindingTarget_TargetPropertyChanged(object sender, EventArgs e) { _timer.Stop(); _timer.Start(); } private void Timer_Tick(object sender, EventArgs e) { _timer.Stop(); _bindingExpression.UpdateSource(); } public static object SetBinding(DependencyObject bindingTarget, DependencyProperty bindingTargetProperty, TimeSpan delay, Binding binding) { // Override some specific settings to enable the behavior of delay binding binding.Mode = BindingMode.TwoWay; binding.UpdateSourceTrigger = UpdateSourceTrigger.Explicit; // Apply and evaluate the binding var bindingExpression = BindingOperations.SetBinding(bindingTarget, bindingTargetProperty, binding); // Setup the delay timer around the binding. This object will live as long as the target element lives, since it subscribes to the changing event, // and will be garbage collected as soon as the element isn't required (e.g., when it's Window closes) and the timer has stopped. new DelayBinding(bindingExpression, bindingTarget, bindingTargetProperty, delay); // Return the current value of the binding (since it will have been evaluated because of the binding above) return bindingTarget.GetValue(bindingTargetProperty); } }
参考
Automatically validating business entities in WPF using custom binding and attributes
作者:旭东
出处:http://www.cnblogs.com/HQFZ
关于作者:专注于微软平台项目架构、管理和企业解决方案。现主要从事WinForm、ASP.NET、WPF、WCF、等方面的项目开发、架构、管理。如有问题或建议,请不吝指教!
本文版权归作者,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接。如有问题,可以联系我,非常感谢。
如果您该文觉得不错或者对你有帮助,请点下推荐,让更多的朋友看到,谢谢!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?