Xamarin Forms - 使用可绑定布局访问模型的不同部分

Xamarin Forms - Using bindable layout to access different parts of the model

我正在尝试设置图片库,它还具有使用 MVVM 过程单击图片以 show/hide 带有图片描述的网格的功能。

但是,我认为我的模型、视图模型和视图设置不正确,因为如果我在顶部堆栈布局中使用 BindableLayout.ItemsSource="{Binding GalleryList.Gallery}",我只能在堆栈布局中显示图像,但无法访问class 的其他部分,即只有图库列表。

所以基本上,我无法访问 InfoGridVisible 绑定,因为它不能 find/reach 吗? (我不确定是否诚实)。

这是我目前的工作片段:

查看 - testpage.xaml:


<ContentPage
    xmlns="http://xamarin.com/schemas/2014/forms"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    x:Class="testproject.Pages.testpage"
    xmlns:d="http://xamarin.com/schemas/2014/forms/design"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:styles="clr-namespace:testproject.Styles"
    xmlns:behaviours="clr-namespace:testproject.ViewModels"
    mc:Ignorable="d"
    xmlns:pancakeview="clr-namespace:Xamarin.Forms.PancakeView;assembly=Xamarin.Forms.PancakeView"
    xmlns:controls="clr-namespace:ImageCircle.Forms.Plugin.Abstractions;assembly=ImageCircle.Forms.Plugin"
    BackgroundColor="Orange"
    x:Name="Root">
      <ContentPage.Content>
            <ScrollView>
                <Grid 
                    Grid.Row="3">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="*"/>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="Auto"/>

                    </Grid.ColumnDefinitions>

                    <!--PROBLEM STARTS HERE -->
                    <StackLayout x:Name="GalleryStk" Grid.Row="1" Orientation="Vertical" BindableLayout.ItemsSource="{Binding GalleryList.Gallery}" Margin="10,0,10,0">
                        <BindableLayout.ItemTemplate>
                            <DataTemplate>
                                <Grid RowSpacing="5" ColumnSpacing="0">
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="AUTO"/>
                                        <RowDefinition Height="AUTO"/>
                                    </Grid.RowDefinitions>



                                    <Frame x:Name="ImageFrame" CornerRadius="20" Padding="0" IsClippedToBounds="True" Grid.Row="0">
                                        <Image Source="{Binding Image}" Aspect="AspectFill" Grid.RowSpan="2" HorizontalOptions="Center" VerticalOptions="Center">
                                            <Image.GestureRecognizers> 
                                                <TapGestureRecognizer BindingContext="{Binding Source={x:Reference Root}, Path=BindingContext}" Command="{Binding TapCommand}"/>
                                            </Image.GestureRecognizers>
                                        </Image>
                                    </Frame>
                                    <!--<Image Source="ShadowOverlay" Grid.RowSpan="2"  Aspect="Fill" VerticalOptions="End" HorizontalOptions="Fill" />-->

                                    <Grid x:Name="InfoGrid"  RowSpacing="10" ColumnSpacing="10" Grid.Row="0" IsEnabled="False" IsVisible="{Binding GalleryList.InfoGridVisible, Source={x:Reference InfoGrid}}">
                                        <Grid.RowDefinitions>
                                            <RowDefinition Height="AUTO"/>
                                            <RowDefinition Height="25"/>
                                        </Grid.RowDefinitions>
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="5"/>
                                            <ColumnDefinition Width="*"/>
                                            <ColumnDefinition Width="AUTO"/>
                                        </Grid.ColumnDefinitions>

                                            <BoxView Color="Black" Opacity="0.5" CornerRadius="20" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Grid.Row="0" Grid.RowSpan="5" Grid.ColumnSpan="3"/>
                                            <Label Text="{Binding Title}" Padding="10,10,0,0" Grid.Row="0" Grid.ColumnSpan="3" Style="{StaticResource TitleLabel}" LineBreakMode="NoWrap"/>


                                        <!--<controls:CircleImage Source="{Binding ProfileImage}" Aspect="AspectFill" Grid.Row="1" Grid.Column="0" WidthRequest="25" HeightRequest="25" />-->
                                            <Label Text="{Binding Description}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" Padding="10,0,10,0" Grid.Row="1" Grid.RowSpan="4" Grid.ColumnSpan="3" Style="{StaticResource HandleLabel}"/>
                                            <!--<Button Text="See More" x:Name="ExpandContractButton" Clicked="ExpandContractButton_Clicked" Padding="10,0,10,0" Grid.Row="2" Grid.RowSpan="3" Grid.ColumnSpan="3"/>-->


                                        <!--<StackLayout Orientation="Horizontal"  VerticalOptions="Center" Grid.Column="2" Grid.Row="1" Spacing="5">
                                            <Image Source="Eye"/>
                                            <Label Text="{Binding ViewCount, StringFormat='{0:N0}'}" Style="{StaticResource HandleLabel}" />
                                            <Label Text="views" Style="{StaticResource BodyLabel}"/>
                                        </StackLayout>-->
                                    </Grid>

                                </Grid>
                            </DataTemplate>
                        </BindableLayout.ItemTemplate>

                        </StackLayout>
                    </Grid>
            </ScrollView>
    </ContentPage.Content>
</ContentPage>

代码隐藏以供查看 - testpage.xaml.cs

public partial class testpage : ContentPage
    {
        private Image _galleryImage;
        public Grid GalleryInfoGrid;
        private static testpage _instance;

        public UserProfileViewModel vm { get; }

        public static testpage Instance
        {
            get
            {
                if (_instance == null)
                    _instance = new testpage();

                return _instance;
            }
        }

        public testpage()
        {
            InitializeComponent();
            vm = new UserProfileViewModel();
            BindingContext = new UserProfileViewModel();
            //var _galleryInfoGrid = (Grid)Root.FindByName("InfoGrid");
            //_galleryInfoGrid.IsEnabled = true;
            //_galleryInfoGrid.IsVisible = true;

        }

型号:

    {
        public List<GalleryImage> Gallery { get; set; }
        public string InfoGridVisible;
        public string InfoGridEnabled;
    }

    public class GalleryImage
    {
        public string Title { get; set; }
        public string Image { get; set; }
        public string Description { get; set; }
    }

服务(数据):

public class ProfileService
    {
        private static ProfileService _instance;


        public static ProfileService Instance
        {
            get
            {
                if (_instance == null)
                    _instance = new ProfileService();

                return _instance;
            }
        }
public GalleryList GetGallery()
        {
            return new GalleryList
            {
                InfoGridEnabled = "False",
                InfoGridVisible = "False",
                Gallery = new List<GalleryImage>
                {
                    new GalleryImage { Title="sevilla01.jpg", Image = "sevilla01.jpg", Description="Description1Description1Description1Description1 Description1Description1Description1 Description1Description1" },
                    new GalleryImage { Title="sevilla02.jpg", Image = "sevilla02.jpg", Description="Description2 Description1Description1Description1Description1Descript ion1Description1"  },
                    new GalleryImage {Title="sevilla03.jpg", Image = "sevilla03.jpg", Description="Description3Description1Description1Description1"  },
                    new GalleryImage {Title="sevilla04.jpg", Image = "sevilla04.jpg", Description="Description4Description1Description1" },
                    new GalleryImage {Title="sevilla05.jpg", Image = "sevilla05.jpg", Description="Description5Description1" },
                    new GalleryImage {Title="sevilla06.jpg", Image = "sevilla06.jpg", Description="Description6" },
                    new GalleryImage {Title="sevilla07.jpg", Image = "sevilla07.jpg", Description="Description7Description1Description1Description1Description1Description1Description1Description1Description1 Description1" }
                }
            };
        }
    }

查看模型 - UserProfileViewModel.cs:

public class UserProfileViewModel : BindableObject
    {
        //Models
        private Profile _profile;
        private GalleryList _galleryList;
        int taps = 0;
        ICommand tapCommand;

        public UserProfileViewModel()
        {
            Profile = ProfileService.Instance.GetProfile();
            GalleryList = ProfileService.Instance.GetGallery();

            tapCommand = new Command(OnTapped);
        }

        public ICommand TapCommand
        {
            get { return tapCommand; }
        }

        void OnTapped(object s)
        {
            taps++;
            //var info1Grid = testpage.Instance.GalleryInfoGrid;
            //info1Grid.IsVisible = true;
            //info1Grid.IsEnabled = true;
            //GalleryList.InfoGridEnabled = "False";
            //GalleryList.InfoGridVisible = "False";
            Console.WriteLine("parameter: " + taps + " " + GalleryList.InfoGridVisible);
            OnPropertyChanged();
        }

        public Profile Profile
        {
            get { return _profile; }
            set
            {
                _profile = value;
                OnPropertyChanged();
            }
        }
        public GalleryList GalleryList
        {
            get { return _galleryList; }
            set
            {
                _galleryList = value;
                OnPropertyChanged();
            }
        }
    }

对于代码转储表示歉意,任何帮助将不胜感激,因为我已经坚持了几天。 如果有更好的实现方法,我很想听听。

InfoGridVisible 不是 属性,因此在执行查找时绑定将永远找不到它,解决此问题的方法是:

public class GalleryList
{
    public List<GalleryImage> Gallery { get; set; }
    public string InfoGridVisible { get; set; }
    public string InfoGridEnabled { get; set; }
}

我想让你尝试的是这样的:

public class GalleryList : BindableObject { 

    private string _InfoGridVisible { get; set; }
    private string _InfoGridEnabled { get; set; }

    public List<GalleryImage> Gallery { get; set; } 
    public string InfoGridVisible
    {
        get { return _InfoGridVisible; }
        set
        {
            _InfoGridVisible = value;
            OnPropertyChanged();
        }
    }

    public string InfoGridEnabled
    {
        get { return _InfoGridEnabled; }
        set
        {
            _InfoGridEnabled = value;
            OnPropertyChanged();
        }
    }
}
public class GalleryImage : BindableObject {

    private string _Title { get; set; }
    private string _Image { get; set; }
    private string _Description { get; set; }

    public string Title
    {
        get { return _Title; }
        set
        {
            _Title = value;
            OnPropertyChanged();
        }
    }

    public string Image
    {
        get { return _Image; }
        set
        {
            _Image = value;
            OnPropertyChanged();
        }
    }

    public string Description
    {
        get { return _Description; }
        set
        {
            _Description = value;
            OnPropertyChanged();
        }
    }
}

在如何能够在 Command 中获取对象的情况下,您需要告诉您的 TapGesture 如何通过这 2 个选项访问该命令:

<TapGestureRecognizer Command ="{Binding Path=BindingContext.CommandToCall, Source={x:Reference Name=ParentPage}}" CommandParameter="{Binding .}"/>

或者:

<TapGestureRecognizer Command ="{Binding Source={RelativeSource AncestorType={x:Type vm:vmWhereCommandIs}}, Path=CommandToCall}" CommandParameter="{Binding .}"/>

如果您需要更多信息,这里有一些资源:

https://docs.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/data-binding/relative-bindings

https://www.xamarinexpert.it/how-to-correctly-use-databinding-with-listview-and-collectionview/