使用Caliburn Micro时在WPF中手动触发验证

时间:2013-04-04 15:15:17

标签: wpf validation xaml caliburn.micro

我有一个实现IDataErrorInfo(并从Caliburn Micro的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
    }
}

使用Caliburn Micro(仅显示相关部分)绑定到以下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 个答案:

答案 0 :(得分:2)

  

/ *           将IDataErrorInfo实现放在Model类中。           不是你的视图模型。           数据错误在模型中不在ViewModel中。           ViewModel引用模型,           IDataErrorInfo通过绑定与绑定进行通信           绑定中的xaml ValidatesOnDataErrors = True            * /

/* 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>