在XAML / Xamarin中交换ListView Grid(两个网格版本,后面的单个代码)

时间:2015-07-28 14:45:40

标签: c# xaml xamarin xamarin.forms

我正在尝试实现一个按钮,在某些项目的列表和平铺视图之间切换。后面的代码对于两者都是相同的,唯一的区别是显示的内容和属性的大小。目前我已经实现了列表视图,XAML看起来像这样:

  <StackLayout>
    <ListView x:Name="FilesListView"
              ItemsSource="{Binding Files}"
              ItemSelected="FileItemSelected">
      <ListView.ItemTemplate>
        <DataTemplate>
          <ViewCell>
            <ViewCell.View>
              <Grid>
                <Grid.ColumnDefinitions>
                  <ColumnDefinition Width="Auto"/>
                  <ColumnDefinition Width="*"/>
                  <ColumnDefinition Width="Auto"/>
                  <ColumnDefinition Width="Auto"/>
                </Grid.ColumnDefinitions>
                <Image Grid.Column="0" Source="{Binding IsFolder, Converter={StaticResource fileTypeToImageConverter}}" WidthRequest="40" HeightRequest="40" HorizontalOptions="Start"/>
                <Label Grid.Column="1" Text="{Binding Path, Converter={StaticResource pathToFilenameConverter}}" HorizontalOptions="StartAndExpand"/>
                <Label Grid.Column="2" Text="{Binding ModifiedDate, Converter={StaticResource dateConverter}}" HorizontalOptions="EndAndExpand"/>
                <Label Grid.Column="3" Text="{Binding Size, Converter={StaticResource fileSizeConverter}}" HorizontalOptions="EndAndExpand"/>
              </Grid>
            </ViewCell.View>
          </ViewCell>
        </DataTemplate>
      </ListView.ItemTemplate>
    </ListView>
  </StackLayout>

这是局部视图; FileBrowser控件嵌套在包含切换按钮的另一个堆栈布局中。该按钮在XAML中定义如下:

  <ContentPage.ToolbarItems>
    <ToolbarItem Text="Toggle View" Order="Primary" Icon="{Binding ViewIcon}" Command="{Binding ToggleViewCommand}"/>
  </ContentPage.ToolbarItems>

其中ToggleViewCommand是:

    protected void ToggleView()
    {
        FileBrowserControl.ToggleView();
        ViewModel.ToggleViewIcon();
    }

我需要帮助找出如何实施FileBrowserControl.ToggleView();。我需要使用不同的XAML片段(表示平铺视图)动态交换网格XAML,或者在代码中更新网格。在定义tile视图的外观方面,第一个选项似乎更容易,但我不想通过创建FileBrowserXaml.xaml / FileBrowserXaml.xaml.cs来复制逻辑背后的代码,这些代码将具有逻辑相同的代码作为FileBrowser.xaml.cs。对于我想要做的事情,Xamarin的最佳做法是什么?

(作为旁注,这需要跨平台。)

更新:我决定尝试在代码中构建数据模板。到目前为止我有这个:

    public void ToggleView()
    {
        DataTemplate itemTemplate;
        if (_view == FileBrowserView.List)
        {
            itemTemplate = new DataTemplate(() =>
            {
                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(() =>
            {
                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;
    }

我现在遇到的问题是,在平铺视图中,每个项目都在它自己的行上。我希望它们换行(路径应该在图像下面,但是每个路径/图像组合应该与下一个路径/图像组合并排,就像在Windows资源管理器或典型的应用程序启动器中一样)。构建数据模板以实现此目的的最佳方法是什么?网格是正确使用的模板还是有更好的模板?

1 个答案:

答案 0 :(得分:0)

您是否尝试过使用ResourceDictionary和StaticResource?

我想你可以通过将ListView ItemTemplate设置为StaticResource然后让切换按钮切换出用于视图的那个来完成你想要的东西。

以下是我的想法:

<ContentPage>
    <ContentPage.Resources>
       <ResourceDictionary>

          <DataTemplate x:Key="TileViewTemplate">
             <ViewCell>
                <ViewCell.View>
                   <!-- the layout of your template here -->
                </ViewCell.View>
             </ViewCell>
          </DataTemplate>

          <DataTemplate x:Key="ListViewTemplate">
             <ViewCell>
                <ViewCell.View>
                   <!-- the layout of your template here -->
                </ViewCell.View>
             </ViewCell>
          </DataTemplate>

       </ResourceDictionary>
    </ContentPage.Resources>

 <ListView x:Name="FilesListView" ItemsSource="{Binding Files}" 
           ItemsSelected="FileItemSelected"
           ItemTemplate="{StaticResource TileViewTemplate}"/>

</ContentPage>

然后,toggleview命令可以切换ItemTemplate属性。这样您就不必担心两个ListView - 它可以使XAML更易于管理。

只是一个想法,但ResourceDictionary确实对我有帮助。