4

How can I change GridViewItems visibility using property binding?

I can't create another ObservableCollection to filter the one I am using as ItemsSource. I tried to use GridView.ItemContainerStyle to change the GridViewItem style but it seems that it does not work with binding (although it works if I set the value to Collapsed).

<GridView.ItemContainerStyle>
    <Style TargetType="GridViewItem">
        <Setter Property="Visibility" Value="{Binding IsVisible, Converter={StaticResource booleanToVisibilityConverter}}" />
    </Style>
</GridView.ItemContainerStyle>

I also tried to use a DataTemplateSelector. I can hide items with binding but then there are gaps on my GridView because the ItemContainer is still there and does not collapse.

I need the GridView items to be collapsed and not just hidden.

EDIT: Why do I want to get rid of filtered ObservableCollections?

I am trying to mirror 2 GridViews and 1 ListView with the same ItemsSource and SelectedItem both binded with my ViewModel properties Items and Current. Without filters it works as I expect without SelectionChanged events, but with only Two-Way Binding.

But those GridView/Listview must have some differences such as the available items for selection and its DataTemplates. So I am using filtered collections that brought me problems.

For example:

  • GridView1 has Items 1, 2 and 3
  • GridView2 has only Items 1 and 3
  • I select Item 1 of GridView1
  • I select Item 2 of GridView1

When I select Item 1 it also gets selected on GridView2. Good for now. When I select Item 2, Item 1 maintains selected on GridView2. GridView2 should now be without selection but if I force it to it will always deselect Item 2 of GridView2 since SelectedItem of both is Two-Way binded.

I hope this is understandable because English is not my native language.

letiagoalves
  • 11,224
  • 4
  • 40
  • 66
  • Why can't you create a filtered ObservableCollection? – Filip Skakun May 09 '13 at 00:56
  • @FilipSkakun Hello Filip. I added the explanation to the question since it would be difficult to explain on a comment. If you need more info tell me and I will update it. Regards – letiagoalves May 09 '13 at 12:52
  • 1
    Create separate properties in your ViewModel for SelectedItem1 and SelectedItem2. In the setters for these properties, check to see if the value is in the other collection. If it is, set the other SelectedItem to the value. If not, do what happens then (either set it to null or something, not sure what your intention is). – Nate Diamond May 10 '13 at 17:11
  • @NateDiamond +1 thats funny because is what I did to "solve it" for now. First I tried to use `SelectionChanged` events but it came with other problems and then I created different properties of my `ViewModel` to binding. Unnecessary If I could change GridViewItems visibility :/ Anyway thanks for the tip. – letiagoalves May 11 '13 at 16:27
  • Yeah, changing GridViewItem's visibility comes with its own issues, as there is a bunch of space taken up for 'default' and 'empty' values, so you have to go into the Style and remove a bunch of it, including from the VisualStates. Definitely a lot of work versus filtering. – Nate Diamond May 11 '13 at 17:45
  • GridView items to be collapsed and not just hidden Use Convertor chain, make them behave like filter... – dipak Feb 07 '14 at 17:35
  • @Dipak how do you suggest? – letiagoalves Feb 07 '14 at 17:57
  • You need to remove items from ItemSource, if you do not want them to display rather then Hiding them.... Use convertor, take source, Filter, and return filtered collection back to Binding (ItemSource) – dipak Feb 10 '14 at 11:46

2 Answers2

1

So first off, there the style isn't working because WinRT doesn't support bindings in setters apparently (see here). This article does mention a workaround for this issue and hopefully it will work for you (although I have not tried it myself).

In case that doesn't pan out, GridView ultimately is just an ItemsControl so you should be able manually override the layout yourself by setting its ItemsPanel property to a custom panel. You could make a small custom panel like this to use in conjunction with your DataTemplateSelector that was working for collapsing the content of the GridViewItems:

class CustomPanel : Panel
{
    //Children of this panel should be of type GridViewItem (which is the ItemContainer for the
    //ItemsControl)

    protected override Size MeasureOverride(Size availableSize)
    {
        foreach (var child in this.Children)
        {
            var interior = (UIElement)VisualTreeHelper.GetChild(child, 0);
            interior.Measure(availableSize);

            if (interior.DesiredSize.Width == 0 && interior.DesiredSize.Height == 0)
                //Skip this item
            else
            {
                child.Measure(availableSize);
                //Update the total measure of the panel with child.DesiredSize...
            }

            //Return the total calculated size
        }
    }

    protected Size override ArrangeOverride(Size finalSize)
    {
        foreach (var child in this.Children)
        {
            var interior = (UIElement)VisualTreeHelper.GetVisualChild(child, 0);

            if (interior.DesiredSize.Width == 0 || interior.DesiredSize.Height == 0)
                //Skip this item
            else
                //Call child.Arrange with the appropriate arguments and update the total size
                //used...

            //Return the total size used
        }
    }
}

This code could be cleaned up somewhat, but something like this should be able to resolve the issue of dealing with empty GridViewItems showing up.

Community
  • 1
  • 1
Chiune Sugihara
  • 1,179
  • 1
  • 7
  • 14
-1

You can modify GridViewItem visibility from the code behind using the item index. The item index is the same as what you have in your ObservableCollection

var gridViewItem = (GridViewItem)this.GridView.ContainerFromIndex(index);
gridViewItem.Visibility = Visibility.Visible;
nimatra
  • 604
  • 8
  • 19