Issue
I would like to be able to show, ideally animate, the showing of an image/icon in the row when clicking the row and the after the selection has been made, navigate to another page while passing the selected row data id to next page.
I tried to use a Setter property CustomImageSource according to a sample not using mvvm, haven't been able to make it work,please help ( I know the code below is wrong).
The view:
<?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>
the view model:
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);
});
}
Solution
Do you want to achieve the following result?
If so, I notice you used MVVM and want to add animate when showing image.
You can add perperty in your ViewModel. I add Isfavourite
property.
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));
}
}
}
Then you want to show the Image with animate when clicking the row. First of all, we should create an custom image. I add BindableProperty
called Animate
when the value is true, show the image and animate.
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, 0, 1000);
}
}
}
public bool Animate
{
get => (bool)GetValue(AnimateProperty);
set => SetValue(AnimateProperty, value);
}
public CustomImage()
{
}
}
}
Then use this customImage to the CollectionView
(bind same Isfavourite perperty Animate="{Binding Isfavourite}"
IsVisible="{Binding Isfavourite}"
). Note: I do not how is your achievement for your customView,So I delete it, And add SelectionChangedCommand
and SelectionChangedCommandParameter
for 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>
Here is layout background code.
public MainPage()
{
InitializeComponent();
this.BindingContext = new MyViewModel(Navigation);
}
Here is my ViewModel. execute the ColorChangeCommand
when click the item in the collectionview. Set the Isfavourite
to true, show the Image. Then wait for 0.5 second, then navigate to the page1 that show the details information.
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));
});
}
}
Here is Page1
's backgroud code.
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class Page1 : ContentPage
{
public Page1(MyModel myModel)
{
InitializeComponent();
MyLabel.Text = myModel.Name;
}
}
Answered By - Leon Lu - MSFT
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.