【问题标题】:Manually Triggering Validation in WPF while using Caliburn Micro使用 Caliburn Micro 时在 WPF 中手动触发验证
【发布时间】:2013-04-04 15:15:17
【问题描述】:

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

谢谢!

【问题讨论】:

    标签: wpf validation xaml caliburn.micro


    【解决方案1】:

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

    验证中涉及的 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>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-27
      • 2020-05-22
      • 1970-01-01
      • 2019-02-06
      • 1970-01-01
      • 1970-01-01
      • 2021-01-10
      • 1970-01-01
      相关资源
      最近更新 更多