3
\$\begingroup\$

I have some markup:

<Window.Resources>
    <CollectionViewSource x:Key="cvsStudentList" Source="{StaticResource StudentList}" Filter="CollectionViewSource_Filter">
    </CollectionViewSource>
</Window.Resources>

It sets up a CollectionViewSource and implements a Filter handler:

private void CollectionViewSource_Filter(object sender, FilterEventArgs e)
{
    Student oStudent = e.Item as Student;
    if (oStudent != null &&
        textStudentFilter != null &&
        checkGenderMale != null &&
        checkGenderFemale != null &&
        checkNeverAssigned != null &&
        checkElder != null &&
        checkMinisterialServant != null &&
        checkNotAppointed != null &&
        checkRegularPioneer != null &&
        checkPublisher != null &&
        checkUnbaptisedOrStudying != null)
    {
        bool bFilterGenderOK = false;
        bool bFilterNameOK = false;
        bool bFilterNeverAssignedOK = false;
        bool bFilterAppointedOK = false;
        bool bFilterServingOK = false;

        // Gender
        if (!checkGenderMale.IsChecked.GetValueOrDefault() && !checkGenderFemale.IsChecked.GetValueOrDefault())
            bFilterGenderOK = true; // We are not filtering gender
        else
        {
            if (checkGenderMale.IsChecked.GetValueOrDefault() && oStudent.Gender == StudentGender.Male)
                bFilterGenderOK = true;
            else if (checkGenderFemale.IsChecked.GetValueOrDefault() && oStudent.Gender == StudentGender.Female)
                bFilterGenderOK = true;
        }

        // Name
        if (textStudentFilter.Text == "")
            bFilterNameOK = true; // We are not filtering the name
        else
        {
            if (oStudent.Name.IndexOf(textStudentFilter.Text, StringComparison.OrdinalIgnoreCase) >= 0)
                bFilterNameOK = true;
        }

        // Never Assigned
        if (!checkNeverAssigned.IsChecked.GetValueOrDefault())
            bFilterNeverAssignedOK = true; // We are not filtering never assigned
        else
            bFilterNeverAssignedOK = oStudent.NeverAssigned;

        // Appointed
        if((checkElder.IsChecked.Value && oStudent.Appointed == StudentAppointed.Elder) ||
            (checkMinisterialServant.IsChecked.Value && oStudent.Appointed == StudentAppointed.MinisterialServant) ||
            (checkNotAppointed.IsChecked.Value && oStudent.Appointed == StudentAppointed.NotAppointed))
        {
            bFilterAppointedOK = true;
        }

        // Serving
        if ((checkRegularPioneer.IsChecked.Value && oStudent.Serving == StudentServing.RegularPioneer) ||
                (checkPublisher.IsChecked.Value && oStudent.Serving == StudentServing.Publisher) ||
                (checkUnbaptisedOrStudying.IsChecked == null && oStudent.Serving == StudentServing.Studying) ||
                (checkUnbaptisedOrStudying.IsChecked.HasValue && checkUnbaptisedOrStudying.IsChecked.Value
                        && (oStudent.Serving == StudentServing.UnbaptisedPublisher || oStudent.Serving == StudentServing.Studying)))
        {
            bFilterServingOK = true;
        }

        if(bFilterGenderOK && bFilterNameOK && bFilterNeverAssignedOK && bFilterAppointedOK && bFilterServingOK)
            e.Accepted = true;
        else
            e.Accepted = false;
    }
}

The controls on the panel:

CheckBoxes

To trigger the view refresh, I have the following handers:

private void textStudentFilter_TextChanged(object sender, TextChangedEventArgs e)
{
    // Refresh the view to apply filters.
    CollectionViewSource.GetDefaultView(gridStudents.ItemsSource).Refresh();
}

private void checkGenderMale_Click(object sender, RoutedEventArgs e)
{
    // Refresh the view to apply filters.
    CollectionViewSource.GetDefaultView(gridStudents.ItemsSource).Refresh();
}

private void checkGenderFemale_Click(object sender, RoutedEventArgs e)
{
    // Refresh the view to apply filters.
    CollectionViewSource.GetDefaultView(gridStudents.ItemsSource).Refresh();
}

private void checkNeverAssigned_Click(object sender, RoutedEventArgs e)
{
    // Refresh the view to apply filters.
    CollectionViewSource.GetDefaultView(gridStudents.ItemsSource).Refresh();
}

private void checkElder_Click(object sender, RoutedEventArgs e)
{
   if (!checkElder.IsChecked.Value && !checkMinisterialServant.IsChecked.Value)
        checkNotAppointed.IsChecked = true;

    // Refresh the view to apply filters.
    CollectionViewSource.GetDefaultView(gridStudents.ItemsSource).Refresh();
}

private void checkMinisterialServant_Click(object sender, RoutedEventArgs e)
{
    if (!checkElder.IsChecked.Value && !checkMinisterialServant.IsChecked.Value)
        checkNotAppointed.IsChecked = true;

    // Refresh the view to apply filters.
    CollectionViewSource.GetDefaultView(gridStudents.ItemsSource).Refresh();
}

private void checkNotAppointed_Click(object sender, RoutedEventArgs e)
{
    // Refresh the view to apply filters.
    CollectionViewSource.GetDefaultView(gridStudents.ItemsSource).Refresh();
}

private void checkRegularPioneer_Click(object sender, RoutedEventArgs e)
{
    // Refresh the view to apply filters.
    CollectionViewSource.GetDefaultView(gridStudents.ItemsSource).Refresh();
}

private void checkPublisher_Click(object sender, RoutedEventArgs e)
{
    // Refresh the view to apply filters.
    CollectionViewSource.GetDefaultView(gridStudents.ItemsSource).Refresh();
}

private void checkUnbaptisedPublisher_Click(object sender, RoutedEventArgs e)
{
    // Refresh the view to apply filters.
    CollectionViewSource.GetDefaultView(gridStudents.ItemsSource).Refresh();
}

private void panelStudentPicker_Loaded(object sender, RoutedEventArgs e)
{
    // Refresh the view to apply filters.
    CollectionViewSource.GetDefaultView(gridStudents.ItemsSource).Refresh();
}

Can this be done in a better way? As you can see, when the check boxes are toggled, or the text box is changed, I want to refresh the filter. This includes when the form is first loaded.

Thank you for any assistance with this.

\$\endgroup\$
  • \$\begingroup\$ I am confused. According to one website it says that the code behind should not have event handlers. That can't be right can it? I was about to add a delegate command to my modelview and get all of the check boxes to call that command when clicked, but none of the controls are visible from the modelview. Only from the code behind (as implemented). Any advice appreciated. \$\endgroup\$ – Andrew Truckle Jun 25 '16 at 15:25
1
\$\begingroup\$

I have resolved this.

  1. Create the view source object in the model view.

  2. Create bool properties in the model view and bind to all check boxes with notification.

  3. Add a command to refresh the source.

  4. Add filter logic to model view

Now it is all done in model view. Filter refreshed as check boxes change.

\$\endgroup\$
  • \$\begingroup\$ In addition to this, I recommend using data annotations on your model for validation. \$\endgroup\$ – RubberDuck Jun 28 '16 at 22:17
  • \$\begingroup\$ Can you please explain ? \$\endgroup\$ – Andrew Truckle Jun 28 '16 at 22:18
  • 1
    \$\begingroup\$ Easier to link. =;)- code.msdn.microsoft.com/windowsdesktop/… \$\endgroup\$ – RubberDuck Jun 28 '16 at 22:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.