1

我有一个像这样实现 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 的验证?

谢谢!

4

1 回答 1

2

/* 将 IDataErrorInfo 实现放在您的模型类中......而不是您的视图模型。数据错误在模型中而不是在视图模型中。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
    }   

验证中涉及的 xml 文本框

 <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}" />

应用程序.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>
于 2014-01-04T06:22:08.547 回答