如何解决Xamarin Forms MVVM单击CollectionView中的一行时显示图标/图像
我希望能够在单击行时显示理想的动画,并在行中显示图像/图标,并在做出选择后导航到另一个页面,同时将选定的行数据ID传递给下一页。
我尝试根据未使用mvvm的示例使用Setter属性CustomImageSource,尚未使其能够正常工作,请帮助(我知道下面的代码是错误的)。
视图:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">
<ContentPage.Resources>
<Style targettype="Grid">
<Setter Property="visualstatemanager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="normal" />
<VisualState x:Name="Selected">
<VisualState.Setters>
<Setter Property="BackgroundColor"
Value="White" />
<Setter Property="CustomImageSource"
Value="select.png" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<ResourceDictionary>
<DataTemplate x:Key="MyCustomCellTemplate">
<Grid>
<customControls:CustomFrame Padding="20"
Margin="20,10,20,10"
HeightRequest="50"
BackgroundColor="{StaticResource frameBackground}"
BorderColor="Transparent"
CornerRadius="5"
HasShadow="True">
<Grid>
<Grid.RowDeFinitions>
<RowDeFinition Height="100*" />
</Grid.RowDeFinitions>
<Grid.ColumnDeFinitions>
<ColumnDeFinition Width="20*" />
<ColumnDeFinition Width="70*" />
<ColumnDeFinition Width="10*" />
</Grid.ColumnDeFinitions>
<Image Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="1"
Source="site_icon">
</Image>
<Label Grid.Row="0"
Grid.Column="1"
HorizontalOptions="Start"
VerticalOptions="Center"
FontSize="Small"
FontAttributes="Bold"
Text="{Binding Name}">
</Label>
<Image x:Name="SelectedIcon"
Grid.Row="0"
Grid.Column="2"
Grid.ColumnSpan="1"
HorizontalOptions="Center"
Source="select.png">
</Image>
</Grid>
</customControls:CustomFrame>
</Grid>
</DataTemplate>
</ResourceDictionary>
</ContentPage.Resources>
<customControls:GradientColorStack StartColor="{StaticResource gradientStartColor}"
EndColor="{StaticResource gradientEndColor}">
<Grid Margin="0" ColumnSpacing="0" RowSpacing="0" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<Grid.RowDeFinitions>
<RowDeFinition Height="8*"/>
<RowDeFinition Height="4*"/>
<RowDeFinition Height="3*"/>
<RowDeFinition Height="80*"/>
</Grid.RowDeFinitions>
<Grid.ColumnDeFinitions>
<ColumnDeFinition Width="20*" />
<ColumnDeFinition Width="80*" />
</Grid.ColumnDeFinitions>
<Label Grid.Row="1"
Grid.ColumnSpan="2"
Text="Select Site"
FontSize="Medium"
TextColor="White"
VerticalOptions="Center"
HorizontalOptions="Center">
</Label>
<BoxView Grid.Row="3"
Grid.ColumnSpan="2"
Grid.RowSpan="4"
BackgroundColor="{StaticResource mainPageBackground}">
</BoxView>
<CollectionView
Grid.Row="4"
Grid.ColumnSpan="2"
EmptyView="No sites for the current user."
ItemsSource="{Binding ItemsCollection}"
ItemTemplate="{StaticResource MyCustomCellTemplate}"
SelectionMode="Single">
</CollectionView>
</Grid>
</customControls:GradientColorStack>
</ContentPage>
视图模型:
public class MyviewmodelClass : BindableBase
{
private Page _currentPage;
private IPageService _pageService;
private List<CollectionItem> _source;
public UserSitesVM(Page currentPage,IPageService pageService)
{
_currentPage = currentPage;
_pageService = pageService;
}
public override async Task InitializeAsync()
{
await PopulateCollection();
}
private async Task PopulateCollection()
{
// code to populate collection
_source = await.........................
ItemsCollection = new ObservableCollection<CollectionItem>(_source);
}
public ObservableCollection<CollectionItem> _itemsCollection
public ObservableCollection<Site> ItemsCollection
{
get
{
return _itemsCollection;
}
set
{
_itemsCollection = value;
RaisePropertyChanged();
}
}
private string _customImageSource;
public string CustomImageSource
{
get
{
return _customImageSource;
}
set
{
_customImageSource = value;
RaisePropertyChanged();
}
}
public static readonly BindableProperty CustomImageSourceProperty = BindableProperty.Create(nameof(CustomImageSource),typeof(string),typeof(Grid),defaultValue: string.Empty,propertyChanged: (SelectedIconSource,oldValue,newValue) =>
{
SelectedIconSource = ImageSource.FromFile((string)newValue);
});
}
解决方法
您想获得以下结果吗?
如果是这样,我注意到您使用了MVVM,并希望在显示图像时添加动画。
您可以在ViewModel中添加性能。我添加了Isfavourite
属性。
public class MyModel: INotifyPropertyChanged
{
string name;
public string Name
{
set
{
if (name != value)
{
name = value;
OnPropertyChanged("Name");
}
}
get
{
return name;
}
}
bool _isfavourite = false;
public bool Isfavourite
{
get
{
return _isfavourite;
}
set
{
if (_isfavourite != value)
{
_isfavourite = value;
OnPropertyChanged("Isfavourite");
}
}
}
string _value;
public string Value
{
set
{
if (_value != value)
{
_value = value;
OnPropertyChanged("Value");
}
}
get
{
return _value;
}
}
private Color _textColor=Color.Green;
public Color TextColor
{
get { return _textColor; }
set
{
_textColor = value;
OnPropertyChanged("TextColor");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this,new PropertyChangedEventArgs(propertyName));
}
}
}
然后,您想在单击该行时显示带有动画的图像。首先,我们应该创建一个自定义图像。当值为true时,我添加名为BindableProperty
的{{1}},显示图像并设置动画。
Animate
然后将这个customImage用于 public class CustomImage:Image
{
public static readonly BindableProperty AnimateProperty =
BindableProperty.Create(nameof(Animate),typeof(bool),typeof(ImageButton),true,propertyChanged: OnEventNameChanged);
private static void OnEventNameChanged(BindableObject bindable,object oldValue,object newValue)
{
if (newValue is bool)
{
bool x = (bool)newValue;
if (x == true)
{
CustomImage customImage= bindable as CustomImage;
// you can add whatever animate here
customImage.FadeTo(1,400);
// customImage.TranslateTo(-100,1000);
}
}
}
public bool Animate
{
get => (bool)GetValue(AnimateProperty);
set => SetValue(AnimateProperty,value);
}
public CustomImage()
{
}
}
}
(将相同的Isfavourite属性CollectionView
Animate="{Binding Isfavourite}"
绑定)。注意:对于您的customView,我不满意您的成就,因此我将其删除,然后为IsVisible="{Binding Isfavourite}"
添加SelectionChangedCommand
和SelectionChangedCommandParameter
CollectionView
这是布局背景代码。
<ContentPage.Resources>
<Style TargetType="Grid">
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Selected">
<VisualState.Setters>
<Setter Property="BackgroundColor"
Value="White" />
<!--<Setter Property="CustomImageSource"
Value="select.png" />-->
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
<ResourceDictionary>
<DataTemplate x:Key="MyCustomCellTemplate">
<Grid>
<customControls:CustomFrame Padding="20"
Margin="20,10,20,10"
HeightRequest="50"
BackgroundColor="Gray"
BorderColor="Transparent"
CornerRadius="5"
HasShadow="True">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20*" />
<ColumnDefinition Width="70*" />
<ColumnDefinition Width="10*" />
</Grid.ColumnDefinitions>
<Image Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="1"
Source="site_icon">
</Image>
<Label Grid.Row="0"
Grid.Column="1"
HorizontalOptions="Start"
VerticalOptions="Center"
FontSize="Small"
FontAttributes="Bold"
Text="{Binding Name}">
</Label>
<customControls:CustomImage x:Name="SelectedIcon"
Grid.Row="0"
Grid.Column="2"
Grid.ColumnSpan="1"
HorizontalOptions="Center"
Animate="{Binding Isfavourite}"
IsVisible="{Binding Isfavourite}"
Source="select.png" >
</customControls:CustomImage>
</Grid>
</customControls:CustomFrame>
</Grid>
</DataTemplate>
</ResourceDictionary>
</ContentPage.Resources>
<!--<customControls:GradientColorStack StartColor="{StaticResource gradientStartColor}"
EndColor="{StaticResource gradientEndColor}">-->
<Grid Margin="0" ColumnSpacing="0" RowSpacing="0" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand">
<Grid.RowDefinitions>
<RowDefinition Height="2*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="1*"/>
<RowDefinition Height="6*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="20*" />
<ColumnDefinition Width="80*" />
</Grid.ColumnDefinitions>
<Label Grid.Row="1"
Grid.ColumnSpan="2"
Text="Select Site"
FontSize="Medium"
TextColor="Black"
VerticalOptions="Center"
HorizontalOptions="Center">
</Label>
<BoxView Grid.Row="3"
Grid.ColumnSpan="2"
Grid.RowSpan="4"
BackgroundColor="WhiteSmoke">
</BoxView>
<CollectionView
x:Name="MyCollectionView"
Grid.Row="4"
Grid.ColumnSpan="2"
EmptyView="No sites for the current user."
ItemsSource="{Binding Stats}"
ItemTemplate="{StaticResource MyCustomCellTemplate}"
SelectionChangedCommand="{Binding ColorChangeCommand}"
SelectionChangedCommandParameter="{Binding SelectedItem,Source={x:Reference MyCollectionView}}"
SelectionMode="Single">
</CollectionView>
</Grid>
<!--</customControls:GradientColorStack>-->
</ContentPage>
这是我的ViewModel。单击集合视图中的项目时,执行 public MainPage()
{
InitializeComponent();
this.BindingContext = new MyViewModel(Navigation);
}
。将ColorChangeCommand
设置为true,显示图像。然后等待0.5秒,然后导航到显示详细信息的page1。
Isfavourite
这是 public class MyViewModel
{
public ObservableCollection<MyModel> Stats { get; set; }
public ICommand ColorChangeCommand { protected set; get; }
public MyViewModel(INavigation navigation)
{
Stats = new ObservableCollection<MyModel>();
Stats.Add(new MyModel() { Name="test1",Value="1" });
Stats.Add(new MyModel() { Name = "test2",Value = "2" });
Stats.Add(new MyModel() { Name = "test3",Value = "3" });
ColorChangeCommand = new Command<MyModel>(async (key) =>
{
key.Isfavourite = !key.Isfavourite;
await Task.Delay(500);
await navigation.PushModalAsync(new Page1(key));
});
}
}
的背景代码。
Page1
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。