This is a migrated thread and some comments may be shown as answers.

multi select list view

7 Answers 295 Views
ListView
This is a migrated thread and some comments may be shown as answers.
Cédric
Top achievements
Rank 1
Cédric asked on 16 Jul 2018, 02:16 PM

Hello,

 

I have two Control Template in listView (SelectionMode Multiple)
It's possible change control template on click ? 
My problem is that it only changes the first one I select.

C#(Selector)

namespace ProtoDesign.Selector
{
    public class VenteBoxOptionSelector : DataTemplateSelector
    {
        public DataTemplate TemplateDefault { get; set; }
        public DataTemplate TemplateClicked { get; set; }
 
        protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
        {
            if (item != null && (Vente)item != null)
                return ((Vente)item).IsSelected ? TemplateClicked : TemplateDefault;
            return TemplateClicked;
        }
    }
}

 

XAML

<telerikDataControls:RadListView Grid.Column="0" BackgroundColor="{StaticResource WhiteColor}" x:Name="rlv1" SelectionChanged="listView_SelectionChanged" SelectionMode="Multiple">
    <telerikDataControls:RadListView.ItemTemplateSelector>
        <Selector:VenteBoxOptionSelector>
            <Selector:VenteBoxOptionSelector.TemplateDefault>
                <DataTemplate>
                    <telerikListView:ListViewTemplateCell>
                        <telerikListView:ListViewTemplateCell.View>
                            <StackLayout  Orientation="Horizontal">
                                <Label Margin="10" Text="{Binding TxtLabel}" />
                                <Label Margin="10" Text="{Binding IsSelected,Mode=TwoWay}" />
                                <Label Margin="10" Text="Texte séparé grace au StackLayout" />
                            </StackLayout>
                        </telerikListView:ListViewTemplateCell.View>
                    </telerikListView:ListViewTemplateCell>
                </DataTemplate>
            </Selector:VenteBoxOptionSelector.TemplateDefault>
            <Selector:VenteBoxOptionSelector.TemplateClicked>
                <DataTemplate>
                    <telerikListView:ListViewTemplateCell>
                        <telerikListView:ListViewTemplateCell.View>
                            <StackLayout  Orientation="Horizontal">
                                <Label Margin="10" Text="{Binding TxtLabel}" />
                                <Label Margin="10" Text="{Binding IsSelected,Mode=TwoWay}" />
                                <Label Margin="10" Text="Essai en cliquant" />
                            </StackLayout>
                        </telerikListView:ListViewTemplateCell.View>
                    </telerikListView:ListViewTemplateCell>
                </DataTemplate>
            </Selector:VenteBoxOptionSelector.TemplateClicked>
        </Selector:VenteBoxOptionSelector>
    </telerikDataControls:RadListView.ItemTemplateSelector>
</telerikDataControls:RadListView >


XAML.CS

private void listView_SelectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
 
            if ((sender as RadListView).SelectedItems != null && (sender as RadListView).SelectedItems.Count() > 0)
                ((sender as RadListView).SelectedItem as Vente).IsSelected = true;
       }


7 Answers, 1 is accepted

Sort by
0
Lance | Senior Manager Technical Support
Telerik team
answered on 16 Jul 2018, 02:45 PM
Hi Cédric,

Can you please also share the Vente class (and any base class)? I need to make sure the model is using PropertyChanged effectively. Although the item's value was updated, unless property changed is invoked, none of the binds will be aware of the change.

Thank you.

Regards,
Lance | Tech Support Engineer, Sr.
Progress Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Cédric
Top achievements
Rank 1
answered on 16 Jul 2018, 02:49 PM

Yes, 

Thank You

public class Vente
{
   
 
    private int keyVente;
    public virtual int KeyVente
    {
        get
        {
            return this.keyVente;
        }
        set
        {
            if ((this.keyVente != value))
            {
                this.keyVente = value;
            }
        }
    }
 
    private String txtLabel;
    public virtual String TxtLabel
    {
        get
        {
            return this.txtLabel;
        }
        set
        {
            if ((this.txtLabel != value))
            {
                this.txtLabel = value;
            }
        }
    }
 
    private bool isSelected;
    public virtual bool IsSelected
    {
        get
        {
            return this.isSelected;
        }
        set
        {
            if ((this.isSelected != value))
            {
                this.isSelected = value;
 
            }
        }
    }
}
0
Lance | Senior Manager Technical Support
Telerik team
answered on 16 Jul 2018, 03:37 PM
Hi Cédric,

Thank you for the prompt response with the model's code.  Indeed, the IsSelected property isn't invoking OnPropertyChanged.

Here's an updated version you can try:

public class Vente : INotifyPropertyChanged
{
    private int keyVente;
    public virtual int KeyVente
    {
        get => keyVente;
        set
        {
            if (keyVente == value)
                return;
 
            keyVente = value;
            OnPropertyChanged();
        }
    }
 
    private string txtLabel;
    public virtual string TxtLabel
    {
        get => txtLabel;
        set
        {
            if (txtLabel == value)
                return;
 
            txtLabel = value;
            OnPropertyChanged();
        }
    }
 
    private bool isSelected;
    public virtual bool IsSelected
    {
        get => isSelected;
        set
        {
            if (isSelected == value)
                return;
 
            isSelected = value;
            OnPropertyChanged();
        }
    }
 
    public event PropertyChangedEventHandler PropertyChanged;
     
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

Let me know how it goes.

Regards,
Lance | Tech Support Engineer, Sr.
Progress Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Cédric
Top achievements
Rank 1
answered on 17 Jul 2018, 07:46 AM

I tried and my problem is not solved.

Only the first (0) SelectedItem remains true, not the others

if ((sender as RadListView).SelectedItems != null && (sender as RadListView).SelectedItems.Count() > 0)
              ((sender as RadListView).SelectedItem as Vente).IsSelected = true;

Thank for help

0
Cédric
Top achievements
Rank 1
answered on 17 Jul 2018, 07:57 AM
Edit :
My problem is on each click on RadListView : 
(sender as RadListView).SelectedItem is ALWAYS (sender as RadListView).SelectedItems[0]
And this never change     
0
Lance | Senior Manager Technical Support
Telerik team
answered on 17 Jul 2018, 02:35 PM
Hi Cédric,

This is expected because SelectedItem will be the first item in SelectedItems. When using MultipleSelection, you should only use the SelectedItems collection. Let me provide two options you can move forward with.


SelectionChanged

I recommend using the NotifyCollectionChangedArgs (e.g. NewItems, OldItems) instead of manually going through the sender and working with the RadListView directly. It is possible to take the approach you had, but you also have to worry about what items to deselect.

Instead, take advantage of the event args. I've attached a demo for you. For your convenience, here is the relevant code:

public partial class MainPage : ContentPage
{
    public MainPage()
    {
        InitializeComponent();
 
        rlv1.ItemsSource = new ObservableCollection<Vente>(Enumerable.Range(1, 20).Select(i => new Vente {KeyVente = i, TxtLabel = $"Item {i}"}));
    }
 
    private void listView_SelectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        switch (e.Action)
        {
            case NotifyCollectionChangedAction.Add:
// If selections were added, iterate over the newly added items and set IsSelected=true
                foreach (Vente item in e.NewItems) item.IsSelected = true;
                break;
            case NotifyCollectionChangedAction.Remove:
// If the event fired because items were removed, iterate over them and set IsSelected to false
                foreach (Vente item in e.OldItems) item.IsSelected = false;
                break;
        }
    }
}


<ContentPage ... >
 
    <Grid>
        <telerikDataControls:RadListView x:Name="rlv1" SelectionChanged="listView_SelectionChanged" SelectionMode="Multiple">
            <telerikDataControls:RadListView.ItemTemplateSelector>
                <local:VenteBoxOptionSelector>
                    <local:VenteBoxOptionSelector.TemplateDefault>
                        <DataTemplate>
                            <listView:ListViewTemplateCell>
                                <StackLayout  Orientation="Horizontal">
                                    <Label Margin="10" Text="{Binding TxtLabel}" />
                                    <Label Margin="10" Text="{Binding IsSelected}" />
                                    <Label Margin="10" Text="Texte séparé grace au StackLayout" />
                                </StackLayout>
                            </listView:ListViewTemplateCell>
                        </DataTemplate>
                    </local:VenteBoxOptionSelector.TemplateDefault>
                    <local:VenteBoxOptionSelector.TemplateClicked>
                        <DataTemplate>
                            <listView:ListViewTemplateCell>
                                <StackLayout  Orientation="Horizontal">
                                    <Label Margin="10" Text="{Binding TxtLabel}" />
                                    <Label Margin="10" Text="{Binding IsSelected}" />
                                    <Label Margin="10" Text="Essai en cliquant" />
                                </StackLayout>
                            </listView:ListViewTemplateCell>
                        </DataTemplate>
                    </local:VenteBoxOptionSelector.TemplateClicked>
                </local:VenteBoxOptionSelector>
            </telerikDataControls:RadListView.ItemTemplateSelector>
        </telerikDataControls:RadListView >
    </Grid>
</ContentPage>

Here is the result ta runtime







ItemTapped

If you want to keep using use your current approach, I recommend switching to the ItemTapped event instead, but still use the event args instead of the sender:

<telerikDataControls:RadListView  ItemTapped="listView__OnItemTapped" ... />


private void listView__OnItemTapped(object sender, ItemTapEventArgs e)
{
    if (e.Item is Vente item)
        item.IsSelected = !item.IsSelected;
}


Other Observations

Another thing I noticed while building the demo, You have TwoWay binding set up for the Label property that shows the value of IsSelected. This would attempt to set the value of IsSelected with an empty string. Remove the TwoWay binding.




I hope this helps!

Regards,
Lance | Tech Support Engineer, Sr.
Progress Telerik
Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
0
Cédric
Top achievements
Rank 1
answered on 17 Jul 2018, 02:59 PM
Thank you very much, problem solved
Tags
ListView
Asked by
Cédric
Top achievements
Rank 1
Answers by
Lance | Senior Manager Technical Support
Telerik team
Cédric
Top achievements
Rank 1
Share this question
or