Home > Net >  How do i manipulate data or values of collection view items?
How do i manipulate data or values of collection view items?

Time:11-10

I am developing an application in .NET MAUI and i have a page with a collection view which is loaded with data. I display the data onto the collection view children. But then i have a problem, I have a stepper and i want when i change the stepper value, the label i named priceLabel to also change in this format (priceLabelValue = new stepper value * price of the current displayed item of collection view). I also have another label outside the collection view and i want to display on it the total price of all items in the collection view.

I have tried all ways i think but all in vain, one of the problems i encountered was that i was unable to access the views i created within the collection view from the code behind.

When i tried to update these children views using the view model i also found out that i could not access the current item of collection view from the view model.

HINT: Am developing a cart page for products.... Hope this will also help

This is my code.

// xaml code

<CollectionView     x:Name="collcn"
                             ItemsSource="{Binding ShoppingBagCollection}"
                             Grid.Row="1"
                            Grid.ColumnSpan="2"
                            EmptyView="NO ITEMS ADDED">
                    


            <CollectionView.ItemTemplate>
                        <DataTemplate x:DataType="model:Cloth">


                   
                       <Grid Padding="0"
                          Grid.ColumnDefinitions="*,*"
                          Grid.RowDefinitions="*,*,*"
                          ColumnSpacing="10"        
                          HeightRequest="160"       
                          HorizontalOptions="FillAndExpand"
                          Margin="20,20,0,20">


                                <Frame Grid.Column="0"
                               Grid.RowSpan="3"
                               Style="{StaticResource CardView}"
                               Margin="30"        
                               HorizontalOptions="Start"
                               IsClippedToBounds="True">


                                    <Image Source="{Binding Image}"
                                       Aspect="Fill"
                                       HeightRequest="100"
                                       WidthRequest="100"/>

                                </Frame>
                                <VerticalStackLayout Grid.Column="1"
                                             Grid.RowSpan="3"
                                             Spacing="5"
                                             HorizontalOptions="Start"
                                             Margin="0,20,20,0">

                                    <Label Text="{Binding Name}"
                                           Style="{StaticResource MediumLabel}"
                                           Grid.Row="0"/>
                              
                           <!-- This label displays current value of stepper-->

                            <Label x:Name="stepperValue"  
                                           Style="{StaticResource MediumLabel}" 
                                           Text="{Binding Source={x:Reference stepper}, Path=Value}"/>

                        
                            <Stepper x:Name="stepper"
                                              Grid.Row="1"
                                              Minimum="1"
                                              Maximum="{Binding Quantity}"
                                              Increment="1"/>

          <!-- This label should display current value of stepper * Price of current Item-->

                            <Label x:Name="price"  
                                   Style="{StaticResource MediumLabel}" 
                                   Grid.Row="2"       
                                   Text="{Binding Price}"/>

                        </VerticalStackLayout>

    </Grid>
  
                </DataTemplate>
                    </CollectionView.ItemTemplate>
                </CollectionView>


        <Grid            
                          Grid.ColumnSpan="2"
                          Grid.Row="2"
                          Padding="0"
                          Grid.ColumnDefinitions="*,*"
                          Grid.RowDefinitions="*,*,*,*"
                          ColumnSpacing="0"
                          HorizontalOptions="FillAndExpand"
                          Margin="20">
        
                <VerticalStackLayout   
                           Grid.RowSpan="4"
                           Grid.Column="0">


 
<!-- This entry should display total price of all items in collection view but i have failed to get a walk around-->

                <Entry x:Name="totalcostLabel"
                       Grid.Row="2"
                       Placeholder="$0.00"   
                       Margin="0,30,0,0"
                       Text="{Binding Source={x:Reference collcn}}"
                       WidthRequest="120"                      
                       HorizontalOptions="Start"
                       IsReadOnly="True"
                       Style="{StaticResource MediumLabel}"/>
                    
                <Label Grid.Row="2"
                       Text="TotalCost" 
                       Margin="0"/>

            </VerticalStackLayout>

// view model I think there is no need to post the view model and code behind because there is no special logic i have added after trying on so many different ways.

Any body to help me and tell me how l can go about that many thanks in advance.

CodePudding user response:

I've tried to reproduce your issue based on your code and found a solution to make it, though there might be other solutions. Try the following code:

First, in your .xaml file, for your stepper add a ValueChanged event, that's stepper_ValueChanged, which would be triggered while the value of stepper changes.

<Stepper x:Name="stepper"                                             
         Grid.Row="1"
         Minimum="1"
         Maximum="{Binding Quantity}"
         Increment="1"                                 
         ValueChanged="stepper_ValueChanged"/>

Then, in .cs file, we generate a stepper_ValueChanged (or automatically generated by vs).

MainPageViewModel vm;
public MainPage()
{
    InitializeComponent();
    vm = new MainPageViewModel();
    this.BindingContext = vm;
}

private void stepper_ValueChanged(object sender, ValueChangedEventArgs e)
{
    double pricetotal = 0;  
    
    // The BindingContext of each stepper is Cloth instance in ObservableCollection. 
    //So here we go through every instance to find which one this stepper is related to.
    
    var stepper = (Stepper)sender;
    foreach (Cloth cloth in vm.ShoppingBagCollection) 
    {
        if(cloth == stepper.BindingContext)
        {
            cloth.Price = cloth.Price / e.OldValue * e.NewValue;
        }
        pricetotal  = cloth.Price;
    }   
    vm.PriceTotal = pricetotal; // // the total price shown in the entry, we will define it later in ViewModel. It also changes while stepper changes.
}

In your Model Cloth, also make some changes. You should implements INotifyPropertyChanged and PropertyChanged event. For more information about INotifyPropertyChanged, you could refer to ViewModels and Property-Change Notifications

public class Cloth : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    public double _price;
    public double Price 
    { 
        get
        {
            return _price;
        }
        set
        {
            _price = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Price)));
        }              
    }
    ......

}

Finally, in ViewModel, define a new property PriceTotal to which entry binds and also implememt the INotifyPropertyChanged.

public class MainPageViewModel :INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;        
    private double _priceTotal;
    
    public double PriceTotal
    {
        get
        {
            return _priceTotal;
        }
        set
        {
            _priceTotal = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(PriceTotal)));
        }
    } 
.......
}

This is the main structure of my solution although I know there should be more details.

Hope my answer could help you.

  • Related