Это - конкретный Linux, но Вы могли использовать:
SELF=$(readlink /proc/$/fd/255)
Я не могу точно понять ваши требования, однако способ, которым я справился с подобной ситуацией, использовать событие CollectionChanged в ObservableCollection и просто создавать / уничтожать модели представления по мере необходимости.
void OnApplesCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
// Only add/remove items if already populated.
if (!IsPopulated)
return;
Apple apple;
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
apple = e.NewItems[0] as Apple;
if (apple != null)
AddViewModel(asset);
break;
case NotifyCollectionChangedAction.Remove:
apple = e.OldItems[0] as Apple;
if (apple != null)
RemoveViewModel(apple);
break;
}
}
Могут возникнуть некоторые проблемы с производительностью при добавлении / удалении большого количества элементов в ListView.
Мы решили эту проблему следующим образом: Расширение коллекции ObservableCollection для добавления методов AddRange, RemoveRange, BinaryInsert и добавление событий, которые уведомляют других об изменении коллекции. Вместе с расширенным CollectionViewSource, который временно отключает источник при изменении коллекции, он отлично работает.
HTH,
Деннис
Ну, во-первых, я не думаю, что есть единственный «правильный способ» сделать это. Это полностью зависит от вашего приложения. Есть способы более правильные и менее правильные.
Так много сказано, мне интересно, зачем вам нужно держать эти коллекции « синхронно ». Какой сценарий, по вашему мнению, может привести к их рассинхронизации? Если вы посмотрите на образец кода из статьи Джоша Смита MSDN о MV-VM , вы увидите, что в большинстве случаев модели синхронизируются с моделями представления просто потому, что каждый раз, когда создается модель , также создается ViewModel. Как это:
void CreateNewCustomer()
{
Customer newCustomer = Customer.CreateNewCustomer();
CustomerViewModel workspace = new CustomerViewModel(newCustomer, _customerRepository);
this.Workspaces.Add(workspace);
this.SetActiveWorkspace(workspace);
}
Мне интересно, что мешает вам создавать AppleModelView
каждый раз, когда вы создаете Apple
? Мне кажется, что это самый простой способ «синхронизировать» эти коллекции, если только я не понял ваш вопрос неправильно.
Я использую лениво сконструированные, автоматически обновляемые коллекции:
public class BasketModelView
{
private readonly Lazy<ObservableCollection<AppleModelView>> _appleViews;
public BasketModelView(BasketModel basket)
{
Func<AppleModel, AppleModelView> viewModelCreator = model => new AppleModelView(model);
Func<ObservableCollection<AppleModelView>> collectionCreator =
() => new ObservableViewModelCollection<AppleModelView, AppleModel>(basket.Apples, viewModelCreator);
_appleViews = new Lazy<ObservableCollection<AppleModelView>>(collectionCreator);
}
public ObservableCollection<AppleModelView> Apples
{
get
{
return _appleViews.Value;
}
}
}
Используя следующие ObservableViewModelCollection
:
namespace Client.UI
{
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Diagnostics.Contracts;
using System.Linq;
public class ObservableViewModelCollection<TViewModel, TModel> : ObservableCollection<TViewModel>
{
private readonly ObservableCollection<TModel> _source;
private readonly Func<TModel, TViewModel> _viewModelFactory;
public ObservableViewModelCollection(ObservableCollection<TModel> source, Func<TModel, TViewModel> viewModelFactory)
: base(source.Select(model => viewModelFactory(model)))
{
Contract.Requires(source != null);
Contract.Requires(viewModelFactory != null);
this._source = source;
this._viewModelFactory = viewModelFactory;
this._source.CollectionChanged += OnSourceCollectionChanged;
}
protected virtual TViewModel CreateViewModel(TModel model)
{
return _viewModelFactory(model);
}
private void OnSourceCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
for (int i = 0; i < e.NewItems.Count; i++)
{
this.Insert(e.NewStartingIndex + i, CreateViewModel((TModel)e.NewItems[i]));
}
break;
case NotifyCollectionChangedAction.Move:
if (e.OldItems.Count == 1)
{
this.Move(e.OldStartingIndex, e.NewStartingIndex);
}
else
{
List<TViewModel> items = this.Skip(e.OldStartingIndex).Take(e.OldItems.Count).ToList();
for (int i = 0; i < e.OldItems.Count; i++)
this.RemoveAt(e.OldStartingIndex);
for (int i = 0; i < items.Count; i++)
this.Insert(e.NewStartingIndex + i, items[i]);
}
break;
case NotifyCollectionChangedAction.Remove:
for (int i = 0; i < e.OldItems.Count; i++)
this.RemoveAt(e.OldStartingIndex);
break;
case NotifyCollectionChangedAction.Replace:
// remove
for (int i = 0; i < e.OldItems.Count; i++)
this.RemoveAt(e.OldStartingIndex);
// add
goto case NotifyCollectionChangedAction.Add;
case NotifyCollectionChangedAction.Reset:
Clear();
for (int i = 0; i < e.NewItems.Count; i++)
this.Add(CreateViewModel((TModel)e.NewItems[i]));
break;
default:
break;
}
}
}
}
Я написал несколько вспомогательных классов для обертывания наблюдаемых коллекций бизнес-объектов в их аналогах модели представления здесь
Вы также можете найти пример (и пояснения) здесь: http://blog.lexique-du-net.com/index.php ? post / 2010/03/02 / MV-VM-How-to-keep-collections-of-ViewModel-and-Model-in-sync
Надеюсь на эту помощь
Мне очень нравится решение 280Z28. Всего одно замечание. Нужно ли делать циклы для каждого NotifyCollectionChangedAction? Я знаю, что в документах для действий указано «один или несколько элементов», но, поскольку сам ObservableCollection не поддерживает добавление или удаление диапазонов, я думаю, этого никогда не произойдет.