我创建了一个行为,因此我可以在文本框中更改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 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"/>
&#34; element.GetBindingExpression&#34; line总是返回null,我该怎么把它拉下来?
也试过这个,没有好结果:
Binding newBinding = new Binding();
newBinding.ValidatesOnDataErrors = true;
newBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
element.SetBinding(TextBox.TextProperty, newBinding);
有人可以帮忙吗?
感谢。
答案 0 :(得分:0)
如果我理解正确的话,我相信这就是你想要的,当ChangeBindingBehavior上的ValidateDataErrors属性为True时,它会修改Text绑定,使UpdateSourceTrigger的值为UpdateSourceTrigger.PropertyChanged。
注意:要使用这个你需要引用System.Windows.Interactivity,这可以通过任何一个包提供这个程序集(dll)从nuGet获得,有一个正式的MS一个但我可以&#39;似乎找到了这个名字。
XAML:
<TextBox Text="{Binding Path=SomeTextValue}">
<i:Interaction.Behaviors>
<app:ChangeBindingBehavior ValidateDataErrors="True" />
</i:Interaction.Behaviors>
</TextBox>
行为背后的代码:
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);
}
}
答案 1 :(得分:0)
问题是在应用绑定之前调用了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);
}
}
}