title: Swapping out ListView Grid in XAML/Xamarin (Two grid versions, single code behind)
body: <p>I am trying to implement a button that toggles between a list and tile view of some items. The code behind is identical for both and the only difference is the size of what is displayed and the properties. Currently I have the list view implemented and the XAML looks like this:</p>
  
  <pre><code>  &lt;StackLayout&gt;
      &lt;ListView x:Name="FilesListView"
                ItemsSource="{Binding Files}"
                ItemSelected="FileItemSelected"&gt;
        &lt;ListView.ItemTemplate&gt;
          &lt;DataTemplate&gt;
            &lt;ViewCell&gt;
              &lt;ViewCell.View&gt;
                &lt;Grid&gt;
                  &lt;Grid.ColumnDefinitions&gt;
                    &lt;ColumnDefinition Width="Auto"/&gt;
                    &lt;ColumnDefinition Width="*"/&gt;
                    &lt;ColumnDefinition Width="Auto"/&gt;
                    &lt;ColumnDefinition Width="Auto"/&gt;
                  &lt;/Grid.ColumnDefinitions&gt;
                  &lt;Image Grid.Column="0" Source="{Binding IsFolder, Converter={StaticResource fileTypeToImageConverter}}" WidthRequest="40" HeightRequest="40" HorizontalOptions="Start"/&gt;
                  &lt;Label Grid.Column="1" Text="{Binding Path, Converter={StaticResource pathToFilenameConverter}}" HorizontalOptions="StartAndExpand"/&gt;
                  &lt;Label Grid.Column="2" Text="{Binding ModifiedDate, Converter={StaticResource dateConverter}}" HorizontalOptions="EndAndExpand"/&gt;
                  &lt;Label Grid.Column="3" Text="{Binding Size, Converter={StaticResource fileSizeConverter}}" HorizontalOptions="EndAndExpand"/&gt;
                &lt;/Grid&gt;
              &lt;/ViewCell.View&gt;
            &lt;/ViewCell&gt;
          &lt;/DataTemplate&gt;
        &lt;/ListView.ItemTemplate&gt;
      &lt;/ListView&gt;
    &lt;/StackLayout&gt;
  </code></pre>
  
  <p>This is a partial view; the FileBrowser control gets nested in another stack layout that contains the toggle button. The button is defined in XAML like this:</p>
  
  <pre><code>  &lt;ContentPage.ToolbarItems&gt;
      &lt;ToolbarItem Text="Toggle View" Order="Primary" Icon="{Binding ViewIcon}" Command="{Binding ToggleViewCommand}"/&gt;
    &lt;/ContentPage.ToolbarItems&gt;
  </code></pre>
  
  <p>where ToggleViewCommand is:</p>
  
  <pre><code>    protected void ToggleView()
      {
          FileBrowserControl.ToggleView();
          ViewModel.ToggleViewIcon();
      }
  </code></pre>
  
  <p>I need help figuring out how to implement <code>FileBrowserControl.ToggleView();</code>. I need to either dynamically swap out the grid XAML with a different XAML snippet (representing the tile view), or update the grid in code. The first option seems easier in terms of defining what the tile view would look like, but I don't want to duplicate the code behind logic by creating FileBrowserXaml.xaml/FileBrowserXaml.xaml.cs which would have the same code behind logic as FileBrowser.xaml.cs. What is the Xamarin best practice for what I'm trying to do?</p>
  
  <p>(As a side note, this needs to be cross platform.)</p>
  
  <hr>
  
  <p><strong>Update:</strong> I decided to try to build the data template in code. I have this so far:</p>
  
  <pre><code>    public void ToggleView()
      {
          DataTemplate itemTemplate;
          if (_view == FileBrowserView.List)
          {
              itemTemplate = new DataTemplate(() =&gt;
              {
                  var cell = new ViewCell();
                  var grid = new Grid();
  
                  // Define columns
                  grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
                  grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
                  grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
                  grid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
  
                  // Define rows
                  var image = new Image
                  {
                      WidthRequest = 40,
                      HeightRequest = 40,
                      HorizontalOptions = LayoutOptions.Start
                  };
                  image.SetBinding(Image.SourceProperty,
                                   new Binding("IsFolder", BindingMode.Default, new FileTypeToImageValueConverter()));
                  grid.Children.Add(image, 0, 0);
  
                  var pathLabel = new Label {HorizontalOptions = LayoutOptions.StartAndExpand};
                  pathLabel.SetBinding(Label.TextProperty,
                                       new Binding("Path", BindingMode.Default, new PathToFilenameValueConverter()));
                  grid.Children.Add(pathLabel, 1, 0);
  
                  var dateLabel = new Label { HorizontalOptions = LayoutOptions.StartAndExpand };
                  dateLabel.SetBinding(Label.TextProperty,
                                       new Binding("ModifiedDate", BindingMode.Default, new DateTimeDisplayValueConverter()));
                  grid.Children.Add(dateLabel, 2, 0);
  
                  var sizeLabel = new Label { HorizontalOptions = LayoutOptions.EndAndExpand };
                  dateLabel.SetBinding(Label.TextProperty,
                                       new Binding("Size", BindingMode.Default, new FileSizeDisplayValueConverter()));
                  grid.Children.Add(sizeLabel, 3, 0);
  
                  cell.View = grid;
                  return cell;
              });
          }
          else
          {
              itemTemplate = new DataTemplate(() =&gt;
              {
                  var cell = new ViewCell();
                  var grid = new Grid();
  
                  // Define columns
                  grid.ColumnDefinitions.Add(new ColumnDefinition {Width = new GridLength(1, GridUnitType.Star)});
                  grid.ColumnDefinitions.Add(new ColumnDefinition {Width = new GridLength(1, GridUnitType.Star)});
  
                  // Define rows
                  var image = new Image
                  {
                      WidthRequest = 80,
                      HeightRequest = 80,
                      HorizontalOptions = LayoutOptions.Start
                  };
                  image.SetBinding(Image.SourceProperty,
                                   new Binding("IsFolder", BindingMode.Default, new FileTypeToImageValueConverter()));
                  grid.Children.Add(image, 0, 0);
  
                  var pathLabel = new Label { HorizontalOptions = LayoutOptions.Start };
                  pathLabel.SetBinding(Label.TextProperty,
                                       new Binding("Path", BindingMode.Default, new PathToFilenameValueConverter()));
                  grid.Children.Add(pathLabel, 0, 1);
  
                  cell.View = grid;
                  return cell;
              });
          }
          FilesListView.ItemTemplate = itemTemplate;
      }
  </code></pre>
  
  <p>The issue I am having now is, in the tile view, every item is on its own row. I want them to wrap (the path should be underneath the image, but each path/image combo should be side-by-side with the next one, like in Windows Explorer or in a typical app launcher). What is the best way to build a data template to achieve this? Is a grid the correct template to use or is there a better one?</p>