说我有两个包含值的字段,我希望ViewModel仅在按下保存按钮时更新。
根据我的研究,使按钮触发对字段的更新的主要两种方法是使代码隐藏在绑定表达式上调用updateSource()或为视图模型添加增加的复杂度以处理中间值。
真的没有办法仅使用XAML触发updateSource吗?
答案 0 :(得分:1)
没有内置的方法可以从XAML触发更新,但是您可以自己构建。例如,您可以使用Microsoft.Xaml.Behaviors.Wpf设置的基础结构。
首先,创建一个可响应XAML触发器执行的操作。该操作由“目标/属性名称”对配置。有了这些信息,Action就知道要在哪个Element中更新哪个属性(在您的情况下是TextBox中的Text属性)。这些属性需要在XAML中设置(请参见下文)。
Invoke方法由XAML中声明的相应触发器(在您的情况下为Button.Click事件,再次参见下文)调用,您不必自己在代码中调用它。
public class UpdateBindingAction : TriggerAction<FrameworkElement>
{
public FrameworkElement Target
{
get { return (FrameworkElement)GetValue(TargetProperty); }
set { SetValue(TargetProperty, value); }
}
public static readonly DependencyProperty TargetProperty =
DependencyProperty.Register(nameof(Target), typeof(FrameworkElement), typeof(UpdateBindingAction), new PropertyMetadata(null));
public string PropertyName
{
get { return (string)GetValue(PropertyNameProperty); }
set { SetValue(PropertyNameProperty, value); }
}
public static readonly DependencyProperty PropertyNameProperty =
DependencyProperty.Register("PropertyName", typeof(string), typeof(UpdateBindingAction), new PropertyMetadata(null));
protected override void Invoke(object parameter)
{
if (Target == null)
return;
if (string.IsNullOrEmpty(PropertyName))
return;
var propertyDescriptor = DependencyPropertyDescriptor.FromName(PropertyName, Target.GetType(), Target.GetType());
if (propertyDescriptor == null)
return;
Target.GetBindingExpression(propertyDescriptor.DependencyProperty).UpdateSource();
}
}
然后,在不会自动更新的XAML中创建绑定
<TextBox x:Name="txt1" Width="200" Text="{Binding String1, Mode=TwoWay, UpdateSourceTrigger=Explicit}" />
<TextBox x:Name="txt2" Width="200" Text="{Binding String2, Mode=TwoWay, UpdateSourceTrigger=Explicit}" />
最后,创建一个包含Click-Event的EventTrigger的按钮,该按钮将执行UpdateSourceAction。 “ b:”命名空间是xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
(来自Microsoft.Xaml.Behaviors.Wpf),“本地:”命名空间是放置UpdateBindingAction的命名空间。
<Button Margin="10" Content="Update">
<b:Interaction.Triggers>
<b:EventTrigger EventName="Click">
<local:UpdateBindingAction Target="{Binding ElementName=txt1}" PropertyName="Text" />
<local:UpdateBindingAction Target="{Binding ElementName=txt2}" PropertyName="Text" />
<!-- ... -->
</b:EventTrigger>
</b:Interaction.Triggers>
</Button>
有一些通用的内置触发器(EventTrigger,PropertyChangedTrigger等)和动作(ChangePropertyAction,CallMethodAction等),但是像这样的实现您自己的添加很有可能。