0

I have a simple class called Person.cs as follows:

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

I have a ViewModel called MainWindowViewModel.cs as follows:

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));
        }
    }

}

I have a Datagrid in MainWindow.xaml as follows:

All is working fine upto this point. Now I want to delete the empty rows in DataGrid when it looses focus. I can do that as below :

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);
        }
    }
}

But I am planning to create something like reusable control, so I cannot typecast item to Person object. So, how can I check if item is null or empty?

Vishal
  • 6,238
  • 10
  • 82
  • 158

5 Answers5

1

Option 1- Generic Type

You could create an interface for the list item type with an IsEmpty method, and make the custom control generic with a type constraint for this interface.

interface IEntity
{
    bool IsEmpty();
}

Then when you enumerate the list items, cast to IEntity:

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

The Person class implements IEntity, and in the IsEmpty method you cachecking the properties

Option 2- Delegate

Provide the custom control with a delegate that checks if the item is empty, which the developer would implement by performing the specific cast and checking of property values.

private Func<object, bool> _emptyCheckCallback;

This can be called when enumerating the items.

if (_emptyCheckCallback(item))
{
    list.Remove(item);
}
CJB
  • 26
  • 3
  • Thank you. It was a great answer. I forgot to use `return;`. So I got an error specifying that `Collection was Changed`. – Vishal Jul 09 '14 at 18:23
0

I am assuming the FirstName property is common to all scenarios? If so, you can refer to an interface instead of the concrete classes. Just ensure that the objects in the collection implements the interface.

TGH
  • 38,769
  • 12
  • 102
  • 135
  • Sorry my mistake in question. FirstName is a property of Person class. – Vishal Jul 09 '14 at 04:07
  • It's not that easy to make something generic if the null checks are on different objects with different properties – TGH Jul 09 '14 at 04:09
  • I would instead recommend that you don't include those objects in the collection. Meaning you filter them out when building the collection so that there is no need for if checks – TGH Jul 09 '14 at 04:10
  • But the data will be entered by user. – Vishal Jul 09 '14 at 04:12
  • @Vishal just wonder, how you bind your `datagrid`, and what should be the `type` of the `ObservableCollection`, if `maindg.Items` can be any `object` – Prisoner Jul 09 '14 at 04:15
  • Yes you are right. I understand that checking for null on different objects and its properties is nearly not possible by generic way, If you can check for an empty row in DataGrid, then I am done. – Vishal Jul 09 '14 at 04:19
0

You can first check if typecasting the object is safe. eg.

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

For different object you can check if else condition.

If you don't want if-else approach then i would recommend the answer by TGH. Since you need first name to check if the object is null then you can refer to interface and type cast the object to that interface. And for double check you can also check "if ( item is Person )".

Paras Mittal
  • 1,159
  • 8
  • 18
  • I have mentioned in question that I am planning to create something like CustomControl. So, the developer who will work on this control will have a different ItemsSource that does not exist now. So, I can't guess what will be the ItemsSource. So I cannot use something like `if (item is Person)`. – Vishal Jul 09 '14 at 04:23
0

You have two options to simply the code

You can make use of dynamic if you are using c# 4.0

eg

    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);
        }
    }

using dynamic you just need to have the required property available in order to be checked

or

typecast only once if the target type is fixed or you have a common interface of a common base class

    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);
        }
    }

also to check both null and empty at the same time you can use the follows

string.IsNullOrEmpty(p.FirstName);
pushpraj
  • 13,458
  • 3
  • 33
  • 50
0

One possible approach is using reflection :

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

  2. Then for each property, get the property's default value and compare it with item's property value. If item's property value equals to default value means current item is not empty and should'nt be removed.

Community
  • 1
  • 1
har07
  • 88,338
  • 12
  • 84
  • 137