2013-04-04 41 views
1

在WPF手动触发验证我有一个实现IDataErrorInfo的(从卡利科技的Screen类派生)视图模型这样同时使用卡利微

public class MyViewModel : Screen, IDataErrorInfo 
{ 
    ... 

    public BindableCollection<MyEntity> Entities { get; set; } 

    public MyEntity SelectedEntity 
    { 
     get { return _entity; } 

     set 
     { 
      _entity = value; 
      OnSelectedEntityChanged(); 
     } 
    } 

    private void OnSelectedEntityChanged() 
    { 
     // implementation 
    } 

    public virtual string Error 
    { 
     get { // implementation } 
    } 

    public virtual string this[string columnName] 
    { 
     get { // implementation } 
    } 

    public void Populating(PopulatingEventArgs e) 
    { 
     // implementation 
    } 
} 

它绑定到使用卡利微(只有以下XAML相关部分显示)

<tk:AutoCompleteBox 
     x:Name="Entities" 
     cal:Message.Attach="[Event Populating] = [Populating($eventArgs)]"  
     SelectedItem="{Binding Path=SelectedEntity, Mode=TwoWay}" 
     HorizontalAlignment="Stretch" 
     FilterMode="None" 
     IsTextCompletionEnabled="True" 
     Text="{Binding SearchText}" 
     ValueMemberPath="Name"> 
     <tk:AutoCompleteBox.ItemTemplate> 
      <DataTemplate> 
       <TextBlock Text="{Binding Name}"></TextBlock> 
      </DataTemplate>        
     </tk:AutoCompleteBox.ItemTemplate>       
    </tk:AutoCompleteBox> 

我遇到的问题是,当我以编程方式更新SelectedEntity属性时,它不会导致验证触发。我尝试了很多不同的可能的解决方案,比如尝试获取绑定表达式并在其上调用ValidateWithoutUpdate(),在XAML中添加触发器,这应该导致验证被触发等,但目前还没有工作。

如何触发最终会调用IDataErrorInfo.Error的验证?

谢谢!

回答

1

/* 放置在您的模型类的IDataErrorInfo的执行.. 不是你的视图模型。 数据错误在Model中,而不在ViewModel中。 的视图模型引用模型, IDataErrorInfo的经由 XAML结合ValidatesOnDataErrors通信中涉及的验证结合 */

/* model */ 
    public class OldBoy : Screen, IOldBoy, IDataErrorInfo 
    { 
     private Guid oldBoyId; 
     public Guid OldBoyId 
     { 
      get 
      { 
       return this.oldBoyId; 
      } 

      set 
      { 
       this.oldBoyId = value; 
       NotifyOfPropertyChange(() => OldBoyId); 
      } 
     } 

     private string firstName; 
     public string Firstname 
     { 
      get 
      { 
       return this.firstName; 
      } 

      set 
      { 
       this.firstName = value; 
       NotifyOfPropertyChange(() => Firstname); 
      } 
     } 

     private string surName; 
     public string Surname 
     { 
      get 
      { 
       return this.surName; 
      } 

      set 
      { 
       this.surName = value; 
       NotifyOfPropertyChange(() => Surname); 
      } 
     } 



     /* include a Property e.g. CanSave in your Model that will be bound 
     to the IsEnabled DependencyProperty ofIsEnabled on your Submit Button 
     Viz. 
     */ 

     public string this[string name] 
     { 
      get 
      { 
       string result = null; 

       if (name == "Firstname") 
       { 
        // force the issue 
        this.CanSave = true; 
        if (string.IsNullOrEmpty(this.Firstname)) 
        { 
         result = "Model says that Firstname must be entered"; 
        } 
       } 

       if (name == "Surname") 
       { 
        // force the issue 
        this.CanSave = true; 
        if (string.IsNullOrEmpty(this.Surname)) 
        { 
         result = "Model says that Surname must be entered"; 
        } 
       } 

       return result; 
      } 
     } 

     public string Error 
     { 
      get 
      { 
       return null; 
      } 
     } 


     private bool canSave; 
     public bool CanSave 
     { 
      get 
      { 
       return this.canSave; 
      } 

      set 
      { 
       if (string.IsNullOrEmpty(this.Firstname) || string.IsNullOrEmpty(this.surName)) 
       { 
        this.canSave = false; 
       } 
       else 
       { 
        this.canSave = true; 
       } 

       NotifyOfPropertyChange(() => CanSave); 
      } 
     } 
    } 

    /* in the ViewModel the underlying class for the edit window */ 

    public class DetailsViewModel : Screen, IDetailsViewModel 
    { 
     private IOldBoy editingOldBoyItem; 
     public IOldBoy EditingOldBoyItem 
     { 
      get 
      { 
       return this.editingOldBoyItem; 
      } 

      set 
      { 
       this.editingOldBoyItem = value; 
       NotifyOfPropertyChange(() => EditingOldBoyItem); 
      } 
     } 
     // elided 
    } 

XAML文本框=真

<Label Grid.Row="00" 
        Grid.Column="00" 
        Content="First Name" /> 
      <TextBox Text="{Binding Path=EditingOldBoyItem.Firstname, ValidatesOnDataErrors=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
        Style="{StaticResource TextBoxCellValidationStyle}" 
        Grid.Row="00" 
        Grid.Column="01"> 
       <i:Interaction.Behaviors> 
        <local:BindableFocusBehavior HasFocus="{Binding SetFocusToFirstName, Mode=TwoWay, UpdateSourceTrigger=Default}" /> 
       </i:Interaction.Behaviors> 
      </TextBox> 
      <Label Grid.Row="01" 
        Grid.Column="00" 
        Content="Surname" /> 
      <TextBox Text="{Binding Path=EditingOldBoyItem.Surname, ValidatesOnDataErrors=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" 
        Validation.ErrorTemplate="{StaticResource ValidationTemplate}" 
        Grid.Row="01" 
        Grid.Column="01"> 

<!-- save button that is disabled when CanSave is false --> 

<Button Content="Save Edit" 
        IsEnabled="{Binding Path=EditingOldBoyItem.CanSave}" 
        x:Name="Save" 
        Margin="4" 
        Template="{StaticResource RedGlassButton}" /> 

app.xaml

<ControlTemplate x:Key="ValidationTemplate"> 
        <DockPanel LastChildFill="True"> 
         <TextBlock DockPanel.Dock="Bottom" 
            FontSize="12" 
            FontWeight="Bold" 
            Foreground="Red"> 
          <TextBlock.ToolTip> 
           <ToolTip Placement="Center" 
             Style="{StaticResource ErrorToolTip}"> 
            <TextBlock Foreground="White"> 
             <TextBlock.Text> 
              <Binding Path="/ErrorContent" /> 
             </TextBlock.Text> 
            </TextBlock> 
           </ToolTip> 
          </TextBlock.ToolTip> 
        </TextBlock> 
         <Border BorderBrush="Red" 
           BorderThickness="1"> 
          <AdornedElementPlaceholder Name="adornerPlaceholder" /> 
         </Border> 
        </DockPanel> 
       </ControlTemplate> 
       <Style x:Key="TextBoxCellValidationStyle" 
        BasedOn="{StaticResource {x:Type TextBox}}" 
        TargetType="{x:Type TextBox}"> 
        <Style.Triggers> 
         <Trigger Property="Validation.HasError" Value="true"> 
          <Setter Property="Background" Value="LightCyan" /> 
          <Setter Property="Foreground" Value="Red" /> 
          <Setter Property="Validation.ErrorTemplate" Value="{StaticResource ValidationTemplate}" /> 
         </Trigger> 
        </Style.Triggers> 
       </Style>