2015-02-10 2 views
0

У меня есть класс под названием Item и ObservableCollection<Item> в моем объекте viewmodel. Я привязываю его к ListBox. Но у Item есть поле под названием Stats, которое является List<Stat>, и я хочу связать его с другим ListBox. Я не могу сделать это ObservableCollection, потому что оба Item и Stat являются частью отдельной библиотеки классов, которые будут использоваться в проектах, отличных от wpf. Я разрабатываю их так, чтобы я мог делать любые изменения, которые я хочу, но я не могу понять, как я должен это делать.WPF: Как я могу наблюдать свойство List для наблюдаемого объекта

Я пытаюсь разработать редактор, чтобы можно было выбрать элемент из первого списка и добавить статистику к выбранному элементу (и далее настроить эти параметры тоже).

Любая помощь будет оценена по достоинству.

ответ

2

Если вы не можете изменить позицию, чтобы держать что-то иное, чем List<StatModifer> то вы не можете делать то, что вы хотите. Вам нужно будет сделать ItemViewModel, который содержит ObserveableCollection<StatModifierViewModel>. Затем добавьте функции ToModel(), которые вернут их в свою модельную форму, когда закончите. Вы должны делать все свои чтения и записи через прокси-сервер модели представления, чтобы повысить ваши события.

public class ViewModel 
{ 
    public ObservableCollection<ItemViewModel> Items { get; set; } 

    public IEnumerable<StatModifierType> StatModifierTypes 
    { 
     get { return Enum.GetValues(typeof(StatModifierType)).Cast<StatModifierType>(); } 
    } 

    public ViewModel() 
    { 
     Items = new ObservableCollection<ItemViewModel>(); 
    } 
} 

public class ItemViewModel : INotifyPropertyChanged 
{ 
    public ItemViewModel(Item item) 
    { 
     if(item == null) 
      throw new ArgumentNullException("item"); 

     Name = item.Name; 
     Id = item.Id; 
     Description = item.Description; 

     //This converts our List<StatModifier> to a IEnumerable<StatModifierViewModel> 
     var enumerableOfStatViewModels = item.Stats.Select(x => new StatModifierViewModel(x)); 

     _stats = new ObservableCollection<StatModifierViewModel>(enumerableOfStatViewModels); 
    } 

    public Item ToModel() 
    { 
     var item = new Item(); 
     item.Name = Name; 
     item.Id = Id; 
     item.Description = Description; 

     //This converts our ObservableCollection<StatModifierViewModel> to a IEnumerable<StatModifier> 
     var enumerableOfStats = Stats.Select(x => x.StatModifierModel); 

     item.Stats = enumerableOfStats.ToList(); 
    } 

    private ObservableCollection<StatModifierViewModel> _stats; 
    private string _name; 
    private string _id; 
    private string _description; 

    public ObservableCollection<StatModifierViewModel> Stats 
    { 
     get { return _stats; } 
     set 
     { 
      if (Equals(value, _stats)) 
       return; 

      _stats = value; 
      OnPropertyChanged(); 
     } 
    } 

    public string Name 
    { 
     get { return _name; } 
     set 
     { 
      if (value == _name) 
       return; 

      _name = value; 
      OnPropertyChanged(); 
     } 
    } 

    public string Id 
    { 
     get { return _id; } 
     set 
     { 
      if (value == _id) 
       return; 

      _id = value; 
      OnPropertyChanged(); 
     } 
    } 

    public string Description 
    { 
     get { return _description; } 
     set 
     { 
      if (value == _description) 
       return; 

      _description = value; 
      OnPropertyChanged(); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 
    { 
     var handler = PropertyChanged; 
     if (handler != null) 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

public class StatModifierViewModel : INotifyPropertyChanged 
{ 
    private readonly StatModifier _statModifier; 

    public StatModifierViewModel(StatModifier statModifier) 
    { 
     //This needs to not be null to not blow up the other functions. 
     if(statModifier == null) 
      throw new ArgumentNullException("statModifier"); 

     _statModifier = statModifier; 
    } 

    public string StatId 
    { 
     get { return _statModifier.StatId; } 
     set 
     { 
      if (Equals(_statModifier.StatId, value)) 
       return; 

      _statModifier.StatId = value; 
      OnPropertyChanged(); 
     } 
    } 

    public StatModifierType Type 
    { 
     get { return _statModifier.Type; } 
     set 
     { 
      if (Equals(_statModifier.Type, value)) 
       return; 

      _statModifier.Type = value; 
      OnPropertyChanged(); 
     } 
    } 

    public float Value 
    { 
     get { return _statModifier.Value; } 
     set 
     { 
      if (Equals(_statModifier.Value, value)) 
       return; 

      _statModifier.Value = value; 
      OnPropertyChanged(); 
     } 
    } 


    public StatModifier StatModifierModel 
    { 
     get { return _statModifier; } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 
    { 
     var handler = PropertyChanged; 
     if (handler != null) 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
    } 
} 
1

Почему бы вам не сделать INotifyPropertyChanged?

public class Stat : INotifyPropertyChanged 
{ 
    private int _your_property; 
    public int your_property { 
     get { return _your_property; } 
     set { 
      _your_property = value; 
      NotifyPropertyChanged("your_property"); 
     } 
    } 


    public event PropertyChangedEventHandler PropertyChanged; 
    private void NotifyPropertyChanged(string propertyName) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (null != handler) { 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 
+0

поле я пытаюсь наблюдать это ** Список **, так что я думаю, я должен создать мой собственный IList, INotifyPropertyChanged захватить добавлять и удалять событие? – Talemon

+0

@ Талемон, может быть, я не понимаю ваш сценарий. Какие классы вы ** можете ** и какие вы ** не можете редактировать? Вы хотите контролировать изменение количества элементов или содержимого каждого элемента? – fillobotto

+0

Вы можете увидеть классы здесь: http://pastebin.com/pmZdu34e Я назвал StatModifier как Stat, чтобы упростить вопрос, Stat - это другой класс в этом случае. Проблема является общедоступной ObservableCollection Элементы {get; задавать; }, но поле статистики элемента, которое является списком , не наблюдается. – Talemon

0

Вы можете создать еще одно свойство для наблюдаемой статистики. См. Приведенный ниже код.

class Item 
{ 
    private List<Stat> stat; 

    public List<Stat> Stats 
    { 
     get { return stat; } 
     set { stat = value; } 
    } 

    public ObservableCollection<Stat> ObservableStats 
    { 
     get { return new ObservableCollection<Stat>(stat); }    
    } 

} 
+0

Будет ли он подключен к оригинальному списку? Я чувствую, что он просто создаст новую коллекцию с оригинальными элементами, но не будет передавать никаких изменений в оригинал. – Talemon

Смежные вопросы