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://www.xamarinexpert.it/how-to-correctly-use-databinding-with-listview-and-collectionview/
我正在尝试设置图片库,它还具有使用 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://www.xamarinexpert.it/how-to-correctly-use-databinding-with-listview-and-collectionview/