C# 当dataTemplate验证mvvm wpf时,CanExecute不会禁用按钮
我有一个动态生成的窗口,其中包含一些具有验证规则的文本框。文本框验证正在工作,我可以看到我添加的新样式,但我将IsValid函数链接到CanExecute on save按钮,该按钮始终处于启用状态,即使文本框验证出错。C# 当dataTemplate验证mvvm wpf时,CanExecute不会禁用按钮,c#,wpf,mvvm,datatemplate,C#,Wpf,Mvvm,Datatemplate,我有一个动态生成的窗口,其中包含一些具有验证规则的文本框。文本框验证正在工作,我可以看到我添加的新样式,但我将IsValid函数链接到CanExecute on save按钮,该按钮始终处于启用状态,即使文本框验证出错。 谁能给我一个提示,我错过了什么 这是我的窗户: <ScrollViewer Grid.Row="0" VerticalScrollBarVisibility="Auto"> <ItemsControl ItemsSource = "{B
谁能给我一个提示,我错过了什么 这是我的窗户:
<ScrollViewer Grid.Row="0" VerticalScrollBarVisibility="Auto">
<ItemsControl ItemsSource = "{Binding Path = List}" >
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation = "Horizontal">
<Grid>
<TextBox >
<TextBox.Text>
<Binding Path="Path" UpdateSourceTrigger="PropertyChanged" ValidatesOnDataErrors="True" Mode="TwoWay" ValidatesOnNotifyDataErrors="True">
<Binding.ValidationRules>
<validationrules:FolderValidationRule/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
<TextBox.Style>
<Style TargetType="TextBox">
<Style.Triggers>
<Trigger Property="Validation.HasError" Value="True">
<Setter Property="Background" Value="Pink"/>
<Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)[0].ErrorContent}"/>
</Trigger>
</Style.Triggers>
</Style>
</TextBox.Style>
</TextBox>
</Grid>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</ScrollViewer>
<Button Grid.Row="1" Content="Save" Command="{Binding ApplyChanges, Mode=TwoWay}" CommandParameter="{Binding ElementName=EditNewForm}" VerticalAlignment="Bottom" Width="114" Height="23" Margin="246,0,34,7"/>
命令:
public RelayCommand<Window> ApplyChanges { get; private set; }
ApplyChanges = new RelayCommand<Window>(ApplyChangesCommand, CanSaveExecute);
public RelayCommand ApplyChanges{get;private set;}
ApplyChanges=新的RelayCommand(ApplyChangesCommand,CanSaveExecute);
以及守则:
private bool IsValid(DependencyObject obj)
{
if (obj != null)
{
return !Validation.GetHasError(obj) && LogicalTreeHelper.GetChildren(obj).OfType<DependencyObject>().All(IsValid);
}
return true;
}
private bool CanSaveExecute(Window sender)
{
bool valid = IsValid(sender as DependencyObject);
return valid;
}
private bool有效(DependencyObject obj)
{
如果(obj!=null)
{
return!Validation.GetHasError(obj)和&logicaltreeheloper.GetChildren(obj).OfType().All(IsValid);
}
返回true;
}
私有bool CanSaveExecute(窗口发送器)
{
bool valid=IsValid(发送方作为DependencyObject);
返回有效;
}
我假设您的RelayCommand
实现有如下内容:
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
这将把控制权交给UI,以便在感觉合适时查询CanExecute
条件,而要准确地告诉您这是什么时候并不容易。在大多数情况下,它工作得很好,但并不总是如此。有时,如果重新查询未按预期工作,则必须强制执行。只需调用下面的静态方法:
CommandManager.InvalidateRequerySuggested();
这将使命令绑定无效,并强制UI查询使用它的所有UI元素的
CanExecute
条件。很难说您将在哪里调用它,因为问题中没有代码,但我想您的DataContext知道文本框中的文本何时更改。每当绑定到文本框的对象发生更改时,尝试调用它。这不是最漂亮的方法,但它总是有效的。您能显示“我将IsValid函数链接到CanExecute on save按钮”的代码吗?最可能的问题是,CanExecute()
没有被重新查询,因为UI不知道它需要被查询。您是否在其中设置了断点?2美分-如果您使用的是MVVM,请充分使用它,不要在VM中使用窗口引用。现在,您想要实现的,也可以使用DataAnnotations
轻松完成,如果您可以创建一个属性IsValid
,该属性应该基于使用DataAnnotations
表达式验证各种属性来验证您的VM。参考