【问题标题】:How to check if item is null without typecasting it如何在不进行类型转换的情况下检查项目是否为空
【发布时间】:2014-07-09 04:02:13
【问题描述】:

我有一个名为 Person.cs 的简单类,如下所示:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string City { get; set; }
}

我有一个名为 MainWindowViewModel.cs 的 ViewModel,如下所示:

public class MainWindowViewModel : INotifyPropertyChanged
{
    public MainWindowViewModel()
    {
        People = new ObservableCollection<Person>();
    }

    private ObservableCollection<Person> _people;
    public ObservableCollection<Person> People
    {
        get
        {
            return _people;
        }
        set
        {
            _people = value;
            OnPropertyChanged("People");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    protected void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

}

我在 MainWindow.xaml 中有一个 Datagrid,如下所示:

到目前为止一切正常。现在我想在 DataGrid 失去焦点时删除它的空行。我可以这样做:

private void maindg_LostFocus(object sender, RoutedEventArgs e)
{
    var list = (IList)maindg.ItemsSource;
    var elementType = list.GetType().GetGenericArguments()[0];
    var newElement = Activator.CreateInstance(elementType);

    foreach(var item in maindg.Items)
    {
        if((((Person)item).FirstName = null || ((Person)item).FirstName = "") && (((Person)item.LastName) = null || ((Person)item).LastName = "") && (((Person)item).City = null || ((Person)item).City = ""))
        {
            list.Remove(item);
        }
    }
}

但我打算创建类似可重用控件的东西,所以我无法将item 类型转换为Person 对象。那么,如何检查item 是空还是空呢?

【问题讨论】:

    标签: c# wpf datagrid


    【解决方案1】:

    选项 1 - 通用类型

    您可以使用 IsEmpty 方法为列表项类型创建一个接口,并使用此接口的类型约束使自定义控件成为通用控件。

    interface IEntity
    {
        bool IsEmpty();
    }
    

    然后当你枚举列表项时,强制转换为 IEntity:

    var entity = item as IEntity;
    if (entity == null || entity.IsEmpty())
    {
        list.Remove(item);
    }
    

    Person 类实现 IEntity,并在 IsEmpty 方法中缓存属性

    选项 2 - 委托

    为自定义控件提供一个检查项目是否为空的委托,开发人员将通过执行特定的强制转换和检查属性值来实现该委托。

    private Func<object, bool> _emptyCheckCallback;
    

    枚举项时可以调用。

    if (_emptyCheckCallback(item))
    {
        list.Remove(item);
    }
    

    【讨论】:

    • 谢谢。这是一个很好的答案。我忘了使用return;。所以我得到一个错误,指定Collection was Changed
    【解决方案2】:

    我假设 FirstName 属性对所有场景都是通用的?如果是这样,您可以引用接口而不是具体类。只需确保集合中的对象实现了接口即可。

    【讨论】:

    • 抱歉我的错误。 FirstName 是 Person 类的属性。
    • 如果空值检查是针对具有不同属性的不同对象进行的,那么做一些通用的东西并不容易
    • 我建议您不要将这些对象包含在集合中。这意味着您在构建集合时将它们过滤掉,这样就不需要进行 if 检查
    • 但是数据是由用户输入的。
    • @Vishal 只是想知道,你如何绑定你的datagrid,以及ObservableCollectiontype 应该是什么,如果maindg.Items 可以是任何object
    【解决方案3】:

    您可以首先检查类型转换对象是否安全。例如。

     if ( item is Person )
     // safe to typecast now.
    

    对于不同的对象,您可以检查 if else 条件。

    如果您不想要 if-else 方法,那么我会推荐 TGH 的答案。由于您需要名字来检查对象是否为空,因此您可以引用接口并将对象类型转换为该接口。对于仔细检查,您还可以检查“if (item is Person)”。

    【讨论】:

    • 我已经提到我计划创建类似 CustomControl 的东西。因此,将在此控件上工作的开发人员将拥有一个现在不存在的不同 ItemsSource。所以,我无法猜测 ItemsSource 会是什么。所以我不能使用像if (item is Person) 这样的东西。
    【解决方案4】:

    您有两种选择来简化代码

    如果你使用的是 c# 4.0,你可以使用dynamic

    例如

        foreach (dynamic item in maindg.Items)
        {
            if ((item.FirstName = null || item.FirstName = "") && (item.LastName = null || item.LastName = "") && (item.City = null || item.City = ""))
            {
                list.Remove(item);
            }
        }
    

    使用动态您只需要提供所需的属性即可进行检查

    如果目标类型是固定的或者你有一个公共基类的公共接口,则只进行一次类型转换

        foreach (var item in maindg.Items)
        {
            Person p = item as Person;
            if ((p.FirstName = null || p.FirstName = "") && (p.LastName = null || p.LastName = "") && (p.City = null || p.City = ""))
            {
                list.Remove(item);
            }
        }
    

    还可以同时检查 null 和 empty 您可以使用以下命令

    string.IsNullOrEmpty(p.FirstName);
    

    【讨论】:

      【解决方案5】:

      一种可能的方法是使用反射:

      1. Use reflection to get all properties of each item.

      2. 然后对于每个属性,get the property's default value 并进行比较 带有item 的属性值。如果item的属性值等于默认值意味着当前item不为空,不应该被删除。

      【讨论】:

        猜你喜欢
        • 2010-12-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-06-28
        • 1970-01-01
        相关资源
        最近更新 更多