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

时间:2018-04-18 16:42:38

标签: c# wpf mvvm datatemplate

我有一个动态生成的窗口,其中包含一些具有验证规则的文本框。文本框验证工作正常,我可以看到我添加的新样式,但是我将IsValid函数链接到保存按钮上的CanExecute并且按钮始终处于启用状态,即使文本框验证错误。 任何人都可以给我一个暗示我缺少的东西吗? 这是我的窗口:

<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);

和代码:

 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;
    }

1 个答案:

答案 0 :(得分:1)

我假设您的RelayCommand实现具有以下内容:

public event EventHandler CanExecuteChanged
{
  add { CommandManager.RequerySuggested += value; }
  remove { CommandManager.RequerySuggested -= value; }
}

这会将控件移交给UI,以便在感觉合适时查询CanExecute条件,并且确切地告诉您何时这样做并不是一件容易的事。在大多数情况下,它运作良好,但并非总是如此。有时,如果Requery没有按预期工作,则必须强制它。只需调用以下静态方法:

CommandManager.InvalidateRequerySuggested();

这将使命令绑定无效并强制UI查询使用它的所有UI元素的CanExecute条件。很难说你会在哪里调用,因为问题中没有代码,但我想你的DataContext知道文本在有问题的TextBox中何时发生变化。每当绑定到TextBox的对象发生更改时,请尝试调用它。不是最漂亮的方法,但它始终有效。