简体   繁体   中英

IsSynchronizedWithCurrentItem not working when ListView is bound to an ICollectionView with a Converter

I have the an ICollectionView in my ViewModel:

public class ContactsPanelViewModel : ViewModelBase
{
    private ICollectionView accountContactsView;
    public ICollectionView AccountContactsView
    {
        get => accountContactsView;
        set => NotifyPropertyChangedAndSet(ref accountContactsView, value);
    }
public ContactsPanelViewModel()
    {
        AccountContactsView = CollectionViewSource.GetDefaultView(G.AccountContacts); //G.AccountContacts is an IEnumarable<Contact> object
        AccountContactsView.SortDescriptions.Add(new SortDescription("FullName_LastNameFirst", ListSortDirection.Ascending));
        AccountContactsView.CurrentChanged += NewContactSelected;
        AccountContactsView.MoveCurrentToFirst();
    }
}

This is the list it is bound to:

<ListView 
      x:Name="ContactList" 
      HorizontalAlignment="Left" 
      ItemsSource="{Binding Path=AccountContactsView, Converter={StaticResource ContactCardConverter}}"
      IsSynchronizedWithCurrentItem="True"/>

And this is the converter I created:

public class ContactCardConverter : IValueConverter
{
    public object Convert(object Value, Type TargetType, object Parameter, CultureInfo Culture)
    {
        if (Value is ListCollectionView)
        {
            List<ContactCard> contactCards = new List<ContactCard>(); //ContactCard is a UserControl
            ListCollectionView data = Value as ListCollectionView;
            if (data.Count > 0 && data.GetItemAt(0) is Contact)
            {
                foreach(Contact contact in data)
                {
                    contactCards.Add(new ContactCard(contact));
                }
                return contactCards;
            }
            else
            {
                return null;
            }
        }
        else
        {
            return null;
        }
    }

    public object ConvertBack(object Value, Type TargetType, object Parameter, CultureInfo Culture)
    {
        if (Value is ContactCard)
        {
            return (Value as ContactCard).Contact;
        }
        else
        {
            return null;
        }
    }
}

The issue is that because I am using a converter the CurrentItem in my ICollectionView isn't being synchronized when the ListView selection changes. The converter is definitely the issue since removing the converter makes it work perfectly.

I added in a ConvertBack function thinking it would call that if there was a converter used but it didn't work.

I could theoretically make the ICollectionView of the type ContactCard (which is a UserControl), but that doesn't seem like it is how it should be done since from what I understand the ViewModel shouldn't be dependent on how the View will look. This would also add some complecity as I would need to keep the ICollectionView in sync with my actual collection of Contact objects.

What is the proper way to synchronize a ListView and an ICollectionView when the ListView uses a converter?

The proper way is don't use a converter.

You shouldn't convert your viewmodel-CollectionView to the List (as in your case) or another CollectionView in converter, because otherwise in case you created a CollectionView in converter you will synchronize your view (and IsSynchronizedWithCurrentItem works good) against in converter created collection . List can't be synchronized, because it does not implement IColectionView and has not CurrentItem .

The proper way is don't use a converter and put ContactCard -UserControl to the ListView.ItemTemplate .

<ListView.ItemTemplate>
    <DataTemplate>
        <youCustomCtlNameSpace:ContactCard Contact="{Binding}"/>
     </DataTemplate>
</ListView.ItemTemplate>

If you mandatory wants to use a converter, then IsSynchronizedWithCurrentItem makes no sense and you have to synchronize V and VM by yourself via binding with converter to ListView.SelectedItem and your Contact have to hold reference to the UI-object(It's MVVM conform, if you have no dependencies to View see: Is MVVM pattern broken? ). But as I already noted it's not a preferred way!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM