C# BindingExpression在Textbox上始终返回null
我创建了一个行为,以便可以更改文本框上的UpdateSourceTriggerC# BindingExpression在Textbox上始终返回null,c#,wpf,xaml,dependency-properties,behavior,C#,Wpf,Xaml,Dependency Properties,Behavior,我创建了一个行为,以便可以更改文本框上的UpdateSourceTrigger using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Input; using System.Windows.Controls; using GalaSoft.MvvmLight.Command; using Sys
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Input;
using System.Windows.Controls;
using GalaSoft.MvvmLight.Command;
using System.Windows.Data;
namespace xxxxxx.xxx.Behaviors
{
public static class InputBindingValidation
{
public static DependencyProperty ValidateDataErrorsProperty = DependencyProperty.RegisterAttached(
"ValidateDataErrors",
typeof(bool),
typeof(InputBindingValidation),
new UIPropertyMetadata(false, OnValidateDataErrors));
private static void OnValidateDataErrors(DependencyObject target, DependencyPropertyChangedEventArgs e)
{
var element = target as TextBox;
if (element == null)
{
throw new InvalidOperationException("This behavior can be attached to a TextBox item only.");
}
// TEST 1
BindingExpression be = element.GetBindingExpression(TextBox.TextProperty);
if (be != null)
{
be.ParentBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
be.ParentBinding.ValidatesOnDataErrors = true;
element.SetBinding(TextBox.TextProperty, be.ParentBinding);
be.UpdateSource();
}
}
public static void SetValidateDataErrors(DependencyObject d, bool value)
{
d.SetValue(ValidateDataErrorsProperty, value);
}
public static bool GetValidateDataErrors(DependencyObject d)
{
return (bool)d.GetValue(ValidateDataErrorsProperty);
}
}
}
我在xaml中使用它:
<efw:EditViewBase x:Class="DocumentManager.View.DocumentEditView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:efw="clr-namespace:FPLQ.EFW.Base;assembly=FPLQ.EFW"
xmlns:efwcontrol="clr-namespace:FPLQ.EFW.Controls;assembly=FPLQ.EFW.Controls"
xmlns:b="clr-namespace:xxxx.xxx.Behaviors;assembly=FPLQ.EFW"
mc:Ignorable="d"
d:DesignHeight="518" d:DesignWidth="979"
d:DataContext="{Binding Source={StaticResource VMLocator}, Path=DocumentEDVM}">
<GroupBox Style="{StaticResource ResourceKey=MainGrid}" >
<TextBox Grid.Column="1" Grid.Row="0"
Style="{StaticResource TextBoxNotes}"
Text="{Binding Path=EntityViewModel.Title, ValidatesOnDataErrors=True, Mode=TwoWay}"
IsReadOnly="{Binding Path=EntityViewModel.IsReadOnlyNever}"
b:InputBindingValidation.ValidateDataErrors="True"/>
有人能帮忙吗
谢谢。如果我理解正确,我相信这是您想要的,当ChangeBindingBehavior上的ValidateDataErrors属性为True时,它会修改文本绑定,使UpdateSourceTrigger的值为UpdateSourceTrigger.PropertyChanged 注意:要使用此程序集,您需要参考System.Windows.Interactivity,这可以通过提供此程序集(dll)的任何软件包从nuGet获得,有一个官方的MS one,但我似乎找不到名称 XAML:
行为中隐藏的代码:
public sealed class ChangeBindingBehavior : Behavior<TextBox>
{
public static readonly DependencyProperty ValidateDataErrorsProperty = DependencyProperty.Register("ValidateDataErrors",
typeof (bool),
typeof (ChangeBindingBehavior),
new PropertyMetadata(default(bool), OnValidateDataErrorsChanged));
public bool ValidateDataErrors
{
get { return (bool)GetValue(ValidateDataErrorsProperty); }
set { SetValue(ValidateDataErrorsProperty, value); }
}
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.Loaded += OnLoaded;
}
private static void OnValidateDataErrorsChanged(DependencyObject d, DependencyPropertyChangedEventArgs args)
{
if (args.OldValue == args.NewValue)
{
return;
}
((ChangeBindingBehavior)d).OnValidateDataErrorsChanged((bool)args.NewValue);
}
private void OnValidateDataErrorsChanged(bool newValue)
{
if (AssociatedObject == null)
{
return;
}
var expression = AssociatedObject.GetBindingExpression(TextBox.TextProperty);
if (expression != null)
{
if (newValue)
{
var newBinding = new Binding("Text")
{
Path = expression.ParentBinding.Path,
Source = AssociatedObject.DataContext,
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
Mode = expression.ParentBinding.Mode,
Converter = expression.ParentBinding.Converter
};
AssociatedObject.SetBinding(TextBox.TextProperty, newBinding);
AssociatedObject.GetBindingExpression(TextBox.TextProperty).UpdateSource();
}
}
}
private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
{
OnValidateDataErrorsChanged(ValidateDataErrors);
}
}
公共密封类ChangeBindingBehavior:行为
{
公共静态只读DependencyProperty ValidatedataErrorProperty=DependencyProperty.Register(“ValidateDataErrors”,
类型(bool),
类型(ChangeBindingBehavior),
新的PropertyMetadata(默认值(bool),OnValidateDataErrorsChanged);
公共布尔值验证错误
{
获取{return(bool)GetValue(validatedataerrorproperty);}
set{SetValue(validatedataerrorproperty,value);}
}
受保护的覆盖无效附加()
{
base.onatached();
AssociatedObject.Loaded+=已加载;
}
ValidatedataErrorsChanged上的私有静态无效(DependencyObject d、DependencyPropertyChangedEventArgs args)
{
if(args.OldValue==args.NewValue)
{
回来
}
((ChangeBindingBehavior)d).OnValidateDataErrorsChanged((bool)args.NewValue);
}
私有void OnValidateDataErrorsChanged(bool newValue)
{
if(AssociatedObject==null)
{
回来
}
var expression=AssociatedObject.GetBindingExpression(TextBox.TextProperty);
if(表达式!=null)
{
如果(新值)
{
var newBinding=新绑定(“文本”)
{
Path=expression.ParentBinding.Path,
Source=AssociatedObject.DataContext,
UpdateSourceTrigger=UpdateSourceTrigger.PropertyChanged,
Mode=expression.ParentBinding.Mode,
Converter=expression.ParentBinding.Converter
};
AssociatedObject.SetBinding(TextBox.TextProperty,newBinding);
AssociatedObject.GetBindingExpression(TextBox.TextProperty).UpdateSource();
}
}
}
已加载专用void(对象发送方,RoutedEventArgs RoutedEventArgs)
{
OnValidatedataErrors已更改(ValidateDataErrors);
}
}
问题是在应用绑定之前调用了OnValidateDataErrors,因此GetBindingExpression始终返回null。这是我的最终解决方案,效果很好
使用
if (GetValidateDataErrors(target))
element.Initialized += InitializeDataError;
else
element.Initialized -= InitializeDataError;
成功了
完整代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Input;
using System.Windows.Controls;
using GalaSoft.MvvmLight.Command;
using System.Windows.Data;
using xxxx.EFW.Helper;
namespace xxxx.EFW.Behaviors
{
public sealed class InputBindingValidation
{
public static DependencyProperty ValidateDataErrorsProperty = DependencyProperty.RegisterAttached(
"ValidateDataErrors",
typeof(bool),
typeof(InputBindingValidation),
new UIPropertyMetadata(false, OnValidateDataErrors));
private static void OnValidateDataErrors(DependencyObject target, DependencyPropertyChangedEventArgs e)
{
var element = target as TextBox;
if (GetValidateDataErrors(target))
element.Initialized += InitializeDataError;
else
element.Initialized -= InitializeDataError;
}
private static void InitializeDataError(object sender, EventArgs e)
{
var element = sender as TextBox;
if (element == null)
throw new InvalidOperationException("This behavior can be attached to a TextBox item only.");
BindingExpression be = element.GetBindingExpression(TextBox.TextProperty);
if (be != null)
{
Binding bind = new Binding()
{
Path = be.ParentBinding.Path,
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
Mode = be.ParentBinding.Mode,
Converter = be.ParentBinding.Converter,
ValidatesOnDataErrors = true
};
if (be.ParentBinding.Source != null)
bind.Source = be.ParentBinding.Source;
element.SetBinding(TextBox.TextProperty, bind);
}
}
public static void SetValidateDataErrors(DependencyObject d, bool value)
{
d.SetValue(ValidateDataErrorsProperty, value);
}
public static bool GetValidateDataErrors(DependencyObject d)
{
return (bool)d.GetValue(ValidateDataErrorsProperty);
}
}
}
首先,为什么您没有创建一个合适的WPF行为来实现这一点?这里可以找到一个例子——因为我不使用Expression Blend。所以,行为不仅仅是关于Expression Blend的,它们是做你想做的事情的正确方式。你在尝试做什么,这个问题还不清楚?
if (GetValidateDataErrors(target))
element.Initialized += InitializeDataError;
else
element.Initialized -= InitializeDataError;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Input;
using System.Windows.Controls;
using GalaSoft.MvvmLight.Command;
using System.Windows.Data;
using xxxx.EFW.Helper;
namespace xxxx.EFW.Behaviors
{
public sealed class InputBindingValidation
{
public static DependencyProperty ValidateDataErrorsProperty = DependencyProperty.RegisterAttached(
"ValidateDataErrors",
typeof(bool),
typeof(InputBindingValidation),
new UIPropertyMetadata(false, OnValidateDataErrors));
private static void OnValidateDataErrors(DependencyObject target, DependencyPropertyChangedEventArgs e)
{
var element = target as TextBox;
if (GetValidateDataErrors(target))
element.Initialized += InitializeDataError;
else
element.Initialized -= InitializeDataError;
}
private static void InitializeDataError(object sender, EventArgs e)
{
var element = sender as TextBox;
if (element == null)
throw new InvalidOperationException("This behavior can be attached to a TextBox item only.");
BindingExpression be = element.GetBindingExpression(TextBox.TextProperty);
if (be != null)
{
Binding bind = new Binding()
{
Path = be.ParentBinding.Path,
UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
Mode = be.ParentBinding.Mode,
Converter = be.ParentBinding.Converter,
ValidatesOnDataErrors = true
};
if (be.ParentBinding.Source != null)
bind.Source = be.ParentBinding.Source;
element.SetBinding(TextBox.TextProperty, bind);
}
}
public static void SetValidateDataErrors(DependencyObject d, bool value)
{
d.SetValue(ValidateDataErrorsProperty, value);
}
public static bool GetValidateDataErrors(DependencyObject d)
{
return (bool)d.GetValue(ValidateDataErrorsProperty);
}
}
}