C# 当dataTemplate验证mvvm wpf时,CanExecute不会禁用按钮

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

我有一个动态生成的窗口,其中包含一些具有验证规则的文本框。文本框验证正在工作,我可以看到我添加的新样式,但我将IsValid函数链接到CanExecute on save按钮,该按钮始终处于启用状态,即使文本框验证出错。
谁能给我一个提示,我错过了什么 这是我的窗户:

<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。参考