【问题标题】:IsSynchronizedWithCurrentItem not working when ListView is bound to an ICollectionView with a Converter当 ListView 使用转换器绑定到 ICollectionView 时,IsSynchronizedWithCurrentItem 不起作用
【发布时间】:2018-04-30 18:08:24
【问题描述】:

我的 ViewModel 中有一个 ICollectionView:

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();
    }
}

这是绑定到的列表:

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

这是我创建的转换器:

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;
        }
    }
}

问题是因为我使用了转换器,所以当ListView 选择更改时,我的ICollectionView 中的CurrentItem 没有同步。转换器绝对是个问题,因为移除转换器可以使其完美运行。

我添加了一个 ConvertBack 函数,认为如果使用了转换器但它不起作用,它会调用它。

理论上我可以制作ContactCard 类型的ICollectionView(这是一个UserControl),但这似乎不是应该这样做的,因为据我了解ViewModel 不应该依赖关于视图的外观。这也会增加一些复杂性,因为我需要使 ICollectionView 与我的 Contact 对象的实际集合保持同步。

当 ListView 使用转换器时,同步 ListView 和 ICollectionView 的正确方法是什么?

【问题讨论】:

    标签: c# wpf binding uicollectionview converter


    【解决方案1】:

    正确的方法是不要使用转换器。

    您不应该将您的 viewmodel-CollectionView 转换为 List(如您的情况)或转换器中的另一个 CollectionView,否则如果您在转换器中创建 CollectionView,您将同步您的视图(并且 IsSynchronizedWithCurrentItem 有效好)反对在转换器创建的集合中。列表无法同步,因为它没有实现IColectionView,也没有CurrentItem

    正确的方法是不要使用转换器,将ContactCard-UserControl 放到ListView.ItemTemplate

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

    如果你强制想要使用转换器,那么IsSynchronizedWithCurrentItem 没有任何意义,你必须通过将转换器绑定到ListView.SelectedItem 来自己同步 V 和 VM,并且你的 Contact 必须持有对 UI 的引用-对象(它符合 MVVM,如果您没有要查看的依赖项,请参阅:Is MVVM pattern broken?)。但正如我已经指出的,这不是首选方式!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-02-20
      • 2012-08-19
      • 2018-03-26
      • 2011-04-16
      • 1970-01-01
      • 2017-11-09
      • 2013-07-17
      • 1970-01-01
      相关资源
      最近更新 更多