2

I had another question about binding visibility to a listview item and that got answered.

The issue I have now is I am trying to bind visibility to a property of the listview item but it doesn't seem to work.

Here is my code:

<ListView 
    ItemsSource="{Binding FooList}"
    ItemTemplate="{StaticResource FooTemplate}"
    Grid.Row="3">
    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="Padding" Value="0" />
            <Setter Property="MinHeight" Value="0" />
            <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
        </Style>
    </ListView.ItemContainerStyle>
</ListView>

and the template:

<DataTemplate x:Key="FooTemplate">
            <Grid Background="White" HorizontalAlignment="Stretch">
   //template stuff
</Grid>

If I try to set the visibility on the Grid in the template it binds correctly and doesn't display Foo items that it shouldn't, but the space for the container is still there, it's just blank.

If I try to set the visibility binding in the ItemContainer:

<Setter Property="Visibility" Value="{Binding FooVisibility}" />

Then the property FooVisibility never gets called.

What's the appropriate way to hide specific ListView items given that I have an appropriate property that returns a Visibility enum?

JT Smith
  • 361
  • 1
  • 2
  • 15

1 Answers1

6

UWP does not support bindings in Style Setters: https://learn.microsoft.com/en-us/uwp/api/Windows.UI.Xaml.Setter#Windows_UI_Xaml_Setter_Value

You could bind the Visibility property of the root element in the ItemTemplate:

<DataTemplate x:Key="FooTemplate">
    <Grid Background="White" HorizontalAlignment="Stretch" 
          Visibility="{Binding FooVisibility}">

    </Grid>
</DataTemplate>

Or you could write some code that sets up the binding programmatically in an event handler for the DataContextChanged event for the root element as suggested here: https://blog.magnusmontin.net/2016/02/28/disabling-selection-of-some-items-in-a-uwp-listview/

private void Grid_DataContextChanged(FrameworkElement sender, DataContextChangedEventArgs args)
{
    Grid grid = sender as Grid;
    ListViewItem lvi = listView.ContainerFromItem(grid.DataContext) as ListViewItem;
    if (lvi != null)
    {
        lvi.SetBinding(ListViewItem.VisibilityProperty, new Binding() { Path = new PropertyPath("FooVisibility"), Source = grid.DataContext });
    }
}

Alternatively, you could create your own binding helper class:

UWP Binding in Style Setter not working

Universal Apps: How to bind a property of a ListViewItem (container) to the actual item (View Model)?

mm8
  • 163,881
  • 10
  • 57
  • 88
  • When I do that the item doesn't render but the container still does, so I see a blank box where the Foo item that is set to Visibility.Collapsed was – JT Smith Sep 27 '17 at 17:49
  • 1
    Handle the DataContextChanged event for the Grid and set up the binding programmatically. See my edit. – mm8 Sep 27 '17 at 17:53
  • Thanks for all the help. When I add DataContextChanged FooVisibility never gets called. There are no binding errors in the output window. If I set the visibility directly to Collapsed the listview item correctly collapses so this seems like the right path I'm just not sure why FooVisibility never gets called. – JT Smith Sep 27 '17 at 19:06
  • 1
    Ok, you also need to set the Source of the binding to the Grid's DataContext. I edited my answer again. – mm8 Sep 27 '17 at 19:21