我有一个Xamarin.Forms应用程序,并且我想在一个页面中使用CarouselView来显示图像列表。

在该页面上,首先向用户显示总体详细信息,因此此时CarouselView不可见(父框架具有绑定道具IsVisible),并且用户可以在两个选项(内部和外部)之间进行选择,以查看图像。点CarouselView现在对用户可见,并且填充ItemsSource的列表中仅包含有关所选选项的图像。

我的xaml和代码工作正常,但问题是,只有在页面加载时显示CarouselView时,它才有效;如果隐藏了CarouselView,则将发生绑定,但是一旦可见,便不会显示任何内容。我尝试了对可见性和绑定到CarouselView的初始数据进行的许多排列,如果隐藏了Carousel,则它们都不起作用。

我不确定这种行为是否与可见性部分或偶然性无关,而只是用于测试是否使CarouselView默认可见,并且隐藏了“详细信息”(与我想要的功能相反),CarouselView可以正常工作。

我考虑的一种选择是使用2个单独的CarouselView,并根据用户的选择显示/隐藏每个。这样做的问题是,我将在下一版本上有更多选择,因此我需要添加多个对象来控制它。

我在主代码外创建了一个简单的应用程序来复制此行为,尽管我在呈现方式上略有不同,但是如果隐藏了CarouselView,则不加载数据的行为仍在继续。

我的页面的XAML:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:d="http://xamarin.com/schemas/2014/forms/design" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" x:Class="carouseltest.Views.ItemsPage" Title="{Binding Title}" x:Name="BrowseItemsPage">
    <StackLayout>
        <Frame>
            <StackLayout>
                <Button Text="Overall" Clicked="DisplayChanges_OnClick" CommandParameter="-1"/>
                <Button Text="Interior Pictures" Clicked="DisplayChanges_OnClick" CommandParameter="0"/>
                <Button Text="Exterior Pictures" Clicked="DisplayChanges_OnClick" CommandParameter="1"/>
             </StackLayout>
        </Frame>
        <Frame IsVisible="{Binding OverallVisible}">
            <StackLayout>
                <Label Text="{Binding OverallDetails}"/>
            </StackLayout>
        </Frame>
        <Frame IsVisible="{Binding PicturesVisible}">
            <CollectionView ItemsSource="{Binding ImagesSelectedOption}">
                <CollectionView.ItemTemplate>
                    <DataTemplate>
                        <Image Source="{Binding ImagePath}"/>
                    </DataTemplate>
                </CollectionView.ItemTemplate>
            </CollectionView>
        </Frame>
    </StackLayout>
</ContentPage>


.CS文件

public partial class ItemsPage : ContentPage {
    ItemViewModel viewModel;

    public ItemsPage() {
        InitializeComponent();

        BindingContext = viewModel = new ItemViewModel {
            OverallDetails = "House For sale 01",
            Images = new List<DisplayImages> {
                new DisplayImages{  ImagePath = "interior_01", Option=0},
                new DisplayImages{  ImagePath = "interior_02", Option=0},
                new DisplayImages{  ImagePath = "interior_03", Option=0},
                new DisplayImages{  ImagePath = "interior_04", Option=0},
                new DisplayImages{  ImagePath = "exterior_01", Option=1},
                new DisplayImages{  ImagePath = "exterior_02", Option=1},
                new DisplayImages{  ImagePath = "exterior_03", Option=1},
                new DisplayImages{  ImagePath = "exterior_04", Option=1}
            }
        };
    }

    void DisplayChanges_OnClick(object sender, EventArgs e) {
        int selectedValue = -1;
        Button button = sender as Button;
        int.TryParse(button?.CommandParameter?.ToString(), out selectedValue);
        viewModel.overallVisible = selectedValue < 0;
        viewModel.SelectedOption = selectedValue;
    }
    protected override void OnAppearing() {
        base.OnAppearing();
    }
}

public class ItemViewModel : BaseViewModel {

    private int selectedOption = 0;
    public int SelectedOption {
        get { return selectedOption; }
        set {
            selectedOption = value;
            OnPropertyChanged("OverallVisible");
            OnPropertyChanged("PicturesVisible");
            OnPropertyChanged("ImagesSelectedOption");
        }
    }
    public bool overallVisible = true;
    public bool OverallVisible {
        get {
            return overallVisible;
        }
    }

    public bool PicturesVisible {
        get {
            return !overallVisible;
        }
    }

    public string OverallDetails { get; set; }

    public List<DisplayImages> Images { get; set; }

    private Dictionary<int, List<DisplayImages>> imagesSelectedOption = new Dictionary<int, List<DisplayImages>>();
    public List<DisplayImages> ImagesSelectedOption {
        get {
            var selOpt = selectedOption;

            if (!imagesSelectedOption.Keys.Contains(selOpt)) {
                List<DisplayImages> displayImages = new List<DisplayImages>();
                displayImages.AddRange(Images.Where(c => c.Option == selOpt).ToList());
                imagesSelectedOption.Add(selOpt, displayImages);
            }

            return imagesSelectedOption[selOpt];
        }
    }
}

public class DisplayImages {
    public string ImagePath { get; set; }
    public int Option { get; set; }
}


我尝试过的其他方法:
更改具有相同结果的CollectionView的CarouselView。

提前非常感谢您!

编辑:添加显示工作和不工作示例的视图:
https://imgur.com/a/3hQyVoa

编辑2

在@ JuniorJiang-MSFT提出建议后,我使用他的建议更改了示例代码以重新绑定集合,并且我的示例现在正在运行。因此,为了帮助可能从中受益的任何其他人,我在这里添加新代码:

XAML更改-删除了对ItemsSource的出价,为“轮播”添加了名称,因此我可以重新绑定代码:

<ContentPage ...>
        <Frame IsVisible="{Binding PicturesVisible}">
            <CarouselView x:Name="carousel">
                <CarouselView.ItemTemplate>
                    <DataTemplate>
                        <Image Source="{Binding ImagePath}"/>
                    </DataTemplate>
                </CarouselView.ItemTemplate>
            </CarouselView>
        </Frame>
    ...
</ContentPage>


.CS更改-添加了类级别属性,以便在轮播首次显示时重新绑定轮播,更改了按钮代码以重新绑定课程:

private bool carouselBound = false;
...
void DisplayChanges_OnClick(object sender, EventArgs e) {
    int selectedValue = -1;
    Button button = sender as Button;
    int.TryParse(button?.CommandParameter?.ToString(), out selectedValue);

    viewModel.SelectedOption = selectedValue;
    if (selectedValue >= 0) {
        if (!carouselBound) {
            carouselBound = true;
            carousel.SetBinding(CarouselView.ItemsSourceProperty, "ImagesSelectedOption");
        }
        if (carousel.ItemsSource.OfType<object>().Count() > 0)
            carousel.ScrollTo(0, animate: false);

    }
}

最佳答案

我的xaml和代码工作正常,但问题是,只有在页面加载时显示CarouselView时,它才起作用,如果隐藏了CarouselView,则绑定发生,但是一旦可见,则不显示任何内容。


从这种现象来看,Control从隐藏变为可见,数据模型将不会重新加载。

然后,解决方案应通过重新绑定itemsource重新加载数据。

关于c# - CarouselView仅在加载时可见时显示绑定(bind)项目,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57261784/

10-11 12:24