You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF ListView项数据验证及可编辑连接字符串列表实现问询

WPF ListView绑定ObservableCollection的数据验证方案

我来帮你搞定这个ListView项的数据验证问题,结合WPF的标准验证机制,咱们一步步来实现:

1. 让实体类实现验证接口

首先,你的Environment实体类需要实现INotifyDataErrorInfo接口(这是WPF推荐的现代验证接口,比旧的IDataErrorInfo更灵活),同时还要实现INotifyPropertyChanged来支持数据绑定更新。

下面是一个示例实现,假设我们要验证连接字符串不能为空、格式符合基本要求:

using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Text.RegularExpressions;

public class Environment : INotifyPropertyChanged, INotifyDataErrorInfo
{
    private string _connectionString;
    private readonly Dictionary<string, List<string>> _validationErrors = new Dictionary<string, List<string>>();

    public string ConnectionString
    {
        get => _connectionString;
        set
        {
            if (_connectionString != value)
            {
                _connectionString = value;
                ValidateConnectionString(value);
                OnPropertyChanged();
            }
        }
    }

    // 验证连接字符串的逻辑
    private void ValidateConnectionString(string value)
    {
        var errors = new List<string>();
        if (string.IsNullOrWhiteSpace(value))
        {
            errors.Add("连接字符串不能为空");
        }
        // 这里可以添加更复杂的格式验证,比如匹配SQL Server连接字符串的基本结构
        else if (!Regex.IsMatch(value, @"Data Source=.*;Initial Catalog=.*;"))
        {
            errors.Add("连接字符串格式不正确,请检查服务器和数据库名称");
        }

        UpdateErrors(nameof(ConnectionString), errors);
    }

    // 更新错误集合并触发验证状态变化
    private void UpdateErrors(string propertyName, List<string> errors)
    {
        if (errors.Count > 0)
        {
            if (_validationErrors.ContainsKey(propertyName))
                _validationErrors[propertyName] = errors;
            else
                _validationErrors.Add(propertyName, errors);
            ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
        }
        else if (_validationErrors.ContainsKey(propertyName))
        {
            _validationErrors.Remove(propertyName);
            ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
        }
    }

    // INotifyDataErrorInfo 接口实现
    public bool HasErrors => _validationErrors.Any();
    public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
    public IEnumerable GetErrors(string propertyName)
    {
        if (string.IsNullOrEmpty(propertyName) || !_validationErrors.ContainsKey(propertyName))
            return null;
        return _validationErrors[propertyName];
    }

    // INotifyPropertyChanged 接口实现
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

2. 在ListView的ItemTemplate中配置验证反馈

接下来修改你的ListView XAML,添加ItemTemplate,并在输入控件(比如TextBox)上启用验证,同时设置错误提示模板:

<ListView x:Name="DGV_Env" Margin="5" FontSize="11" FontStyle="Italic" 
          ItemsSource="{Binding Environments}" Background="White" 
          HorizontalContentAlignment="Center" VerticalContentAlignment="Center" 
          SelectedIndex="0" SelectionMode="Single" >
    <ListView.Resources>
        <!-- 自定义错误提示模板 -->
        <ControlTemplate x:Key="ValidationErrorTemplate">
            <DockPanel>
                <Border BorderBrush="Red" BorderThickness="1">
                    <AdornedElementPlaceholder />
                </Border>
                <TextBlock Foreground="Red" Margin="5,0,0,0" 
                           Text="{Binding [0].ErrorContent}" />
            </DockPanel>
        </ControlTemplate>

        <Style TargetType="ListViewItem">
            <!-- 你的原有触发器代码 -->
            <Style.Triggers>
                <!-- ... 保留你原来的触发器逻辑 ... -->
            </Style.Triggers>
        </Style>
    </ListView.Resources>

    <!-- 定义ListView项的模板 -->
    <ListView.ItemTemplate>
        <DataTemplate>
            <TextBox Width="300" Margin="2"
                     Text="{Binding ConnectionString, 
                            Mode=TwoWay, 
                            ValidatesOnNotifyDataErrors=True,
                            UpdateSourceTrigger=PropertyChanged}"
                     Validation.ErrorTemplate="{StaticResource ValidationErrorTemplate}" />
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

这里的关键配置:

  • ValidatesOnNotifyDataErrors=True:告诉WPF使用INotifyDataErrorInfo的验证结果
  • UpdateSourceTrigger=PropertyChanged:实时触发验证(也可以用LostFocus延迟验证)
  • 自定义ValidationErrorTemplate:显示红色边框和错误文本,让用户直观看到问题

3. 处理添加/编辑场景的验证

  • 添加新项:当你往ObservableCollection<Environment>里添加新对象时,确保新对象的属性初始化后会触发验证(比如设置空的ConnectionString时,会自动调用验证逻辑)
  • 编辑项:用户修改TextBox内容时,PropertyChanged会触发,同时验证逻辑会实时更新错误状态,UI会自动刷新错误提示

4. 额外优化:禁用无效状态的提交操作

如果有保存按钮之类的操作,可以绑定它的IsEnabled属性到集合的整体验证状态,比如:

// 在ViewModel中添加一个属性
public bool CanSave => !Environments.Any(item => item.HasErrors);

然后在XAML中绑定:

<Button Content="保存" IsEnabled="{Binding CanSave}" Command="{Binding SaveCommand}" />

这样只有当所有项都验证通过时,保存按钮才可用。

内容的提问来源于stack exchange,提问作者madmonk88

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:25:55