Xamarin Forms MVVM单击CollectionView中的一行时显示图标/图像

问题描述

我希望能够在单击行时显示理想的动画,并在行中显示图像/图标,并在做出选择后导航到另一个页面,同时将选定的行数据ID传递给下一页

enter image description here

我尝试根据未使用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);
            });
    }

解决方法

您想获得以下结果吗?

enter image description here

如果是这样,我注意到您使用了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}"添加SelectionChangedCommandSelectionChangedCommandParameter

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