我的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;
}
}
}
问题在于,因为我使用转换器,CurrentItem
选项更改时ICollectionView
ListView
中的ICollectionView
未同步。转换器肯定是问题,因为移除转换器使其工作完美。
我在ConvertBack函数中添加了一个函数,认为如果使用了转换器,它会调用它,但它不起作用。
理论上我可以创建ContactCard
类型的Contact
(这是一个UserControl),但是从我理解的ViewModel应该不应该这样做不依赖于View的外观。这也会增加一些complecity,因为我需要保持ICollectionView与我的实际<!DOCTYPE html>
<html>
<head>
<style>
#map {
height: 400px;
width: 100%;
}
</style>
</head>
<body>
<h3>My Google Maps Demo</h3>
<div id="map"></div>
<script>
function initMap() {
var direccion=[
{
lugar:'CICESE',
lat:31.8675375,
lng: -116.6686867
},
{
lugar: 'Casa',
lat:31.8915163,
lng:-116.6879557
}
];
var uluru = {lat: direccion.lat, lng: direccion.lng};//{lat: -25.363, lng: 131.044};
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: uluru
});
var marker = new google.maps.Marker({
position: uluru,
map: map
});
}
</script>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDgMyVeh8DwebGfZHjiNjyle4xFe9pKSdc&callback=initMap">
</script>
</body>
</html>
对象集合同步。
当ListView使用转换器时,同步ListView和ICollectionView的正确方法是什么?
答案 0 :(得分:0)
正确的方法是不要使用转换器。
您不应该将viewmodel-CollectionView转换为List
(如您的情况)或转换器中的其他CollectionView
,否则如果您在转换器中创建了CollectionView,则会同步您的视图(和IsSynchronizedWithCurrentItem工作正常)反对转换器创建的集合。列表无法同步,因为它未实现IColectionView
且未CurrentItem
。
正确的方法是不使用转换器并将ContactCard
- UserControl放到ListView.ItemTemplate
。
<ListView.ItemTemplate>
<DataTemplate>
<youCustomCtlNameSpace:ContactCard Contact="{Binding}"/>
</DataTemplate>
</ListView.ItemTemplate>
如果你强制要使用转换器,那么IsSynchronizedWithCurrentItem
没有任何意义,你必须自己同步V和VM,通过绑定转换器到ListView.SelectedItem
,你的Contact
必须保持对UI对象的引用(如果你没有依赖于View,请遵守它的MVVM:Is MVVM pattern broken?)。但正如我已经指出的那样,它不是首选方式!