To dość długie pytanie, więc proszę o zachowanie mnie.Caliburn.Micro zagnieżdżona najlepsza praktyka ViewModels
Obecnie opracowuję małe narzędzie, które ma mi pomóc śledzić niezliczone postacie w moich Historiach.
Narzędzie wykonuje następujące operacje:
- obciążenia znaki, które są obecnie przechowywane jako json na dysku i zapisuje je na liście, która zostanie przedstawiona w Shell poprzez ListBox.
- Jeśli użytkownik otworzy następnie znak, Shell, który jest
Conductor<Screen>.Collection.OneActive
, otwiera nowyCharacterViewModel
, który pochodzi zScreen
. - Znak
Character
otrzymuje znak, który zostanie otwarty za pośrednictwem systemu komunikatówIEventAggregator
. - Ponadto,
CharacterViewModel
ma różne właściwości, które są pod ViewModels, które wiążą różne widoki Sub.
I tu jest mój problem: Obecnie zainicjować ViewModels sub ręcznie gdy ChracterViewModel
jest inicjowany. Ale brzmi to dla mnie podejrzanie i jestem pewien, że jest lepszy sposób, aby to zrobić, ale nie widzę, jak powinienem to zrobić.
Oto kod CharacterViewModel
:
/// <summary>ViewModel for the character view.</summary>
public class CharacterViewModel : Screen, IHandle<DataMessage<ICharacterTagsService>>
{
// --------------------------------------------------------------------------------------------------------------------
// Fields
// -------------------------------------------------------------------------------------------------------------------
/// <summary>The event aggregator.</summary>
private readonly IEventAggregator eventAggregator;
/// <summary>The character tags service.</summary>
private ICharacterTagsService characterTagsService;
// --------------------------------------------------------------------------------------------------------------------
// Constructors & Destructors
// -------------------------------------------------------------------------------------------------------------------
/// <summary>Initializes a new instance of the <see cref="CharacterViewModel"/> class.</summary>
public CharacterViewModel()
{
if (Execute.InDesignMode)
{
this.CharacterGeneralViewModel = new CharacterGeneralViewModel();
this.CharacterMetadataViewModel = new CharacterMetadataViewModel();
}
}
/// <summary>Initializes a new instance of the <see cref="CharacterViewModel"/> class.</summary>
/// <param name="eventAggregator">The event aggregator.</param>
[ImportingConstructor]
public CharacterViewModel(IEventAggregator eventAggregator)
: this()
{
this.eventAggregator = eventAggregator;
this.eventAggregator.Subscribe(this);
}
// --------------------------------------------------------------------------------------------------------------------
// Properties
// -------------------------------------------------------------------------------------------------------------------
/// <summary>Gets or sets the character.</summary>
public Character Character { get; set; }
/// <summary>Gets or sets the character general view model.</summary>
public CharacterGeneralViewModel CharacterGeneralViewModel { get; set; }
/// <summary>Gets or sets the character metadata view model.</summary>
public CharacterMetadataViewModel CharacterMetadataViewModel { get; set; }
/// <summary>Gets or sets the character characteristics view model.</summary>
public CharacterApperanceViewModel CharacterCharacteristicsViewModel { get; set; }
/// <summary>Gets or sets the character family view model.</summary>
public CharacterFamilyViewModel CharacterFamilyViewModel { get; set; }
// --------------------------------------------------------------------------------------------------------------------
// Methods
// -------------------------------------------------------------------------------------------------------------------
/// <summary>Saves a character to the file system as a json file.</summary>
public void SaveCharacter()
{
ICharacterSaveService saveService = new JsonCharacterSaveService(Constants.CharacterSavePathMyDocuments);
saveService.SaveCharacter(this.Character);
this.characterTagsService.AddTags(this.Character.Metadata.Tags);
this.characterTagsService.SaveTags();
}
/// <summary>Called when initializing.</summary>
protected override void OnInitialize()
{
this.CharacterGeneralViewModel = new CharacterGeneralViewModel(this.eventAggregator);
this.CharacterMetadataViewModel = new CharacterMetadataViewModel(this.eventAggregator, this.Character);
this.CharacterCharacteristicsViewModel = new CharacterApperanceViewModel(this.eventAggregator, this.Character);
this.CharacterFamilyViewModel = new CharacterFamilyViewModel(this.eventAggregator);
this.eventAggregator.PublishOnUIThread(new CharacterMessage
{
Data = this.Character
});
base.OnInitialize();
}
/// <summary>
/// Handles the message.
/// </summary>
/// <param name="message">The message.</param>
public void Handle(DataMessage<ICharacterTagsService> message)
{
this.characterTagsService = message.Data;
}
}
REALIZACJI Sake ja również daje jedną z ViewModels podrzędnych. Inni nie mają znaczenia, ponieważ są zorganizowani w ten sam sposób, po prostu wykonują różne zadania.
/// <summary>The character metadata view model.</summary>
public class CharacterMetadataViewModel : Screen
{
/// <summary>The event aggregator.</summary>
private readonly IEventAggregator eventAggregator;
/// <summary>Initializes a new instance of the <see cref="CharacterMetadataViewModel"/> class.</summary>
public CharacterMetadataViewModel()
{
if (Execute.InDesignMode)
{
this.Character = DesignData.LoadSampleCharacter();
}
}
/// <summary>Initializes a new instance of the <see cref="CharacterMetadataViewModel"/> class.</summary>
/// <param name="eventAggregator">The event aggregator.</param>
/// <param name="character">The character.</param>
public CharacterMetadataViewModel(IEventAggregator eventAggregator, Character character)
{
this.Character = character;
this.eventAggregator = eventAggregator;
this.eventAggregator.Subscribe(this);
}
/// <summary>Gets or sets the character.</summary>
public Character Character { get; set; }
/// <summary>
/// Gets or sets the characters tags.
/// </summary>
public string Tags
{
get
{
return string.Join("; ", this.Character.Metadata.Tags);
}
set
{
char[] delimiters = { ',', ';', ' ' };
List<string> tags = value.Split(delimiters, StringSplitOptions.RemoveEmptyEntries).ToList();
this.Character.Metadata.Tags = tags;
this.NotifyOfPropertyChange(() => this.Tags);
}
}
}
już czytać na Screens, Conductors and Composition, IResult and Coroutines i odtłuszczonego resztę dokumentacji, ale jakoś nie mogę znaleźć to, czego szukam.
// edit: Powinienem wspomnieć o kodzie, który mam działa dobrze. Po prostu nie jestem z tego zadowolony, ponieważ uważam, że nie rozumiem idei MVVM całkiem dobrze i dlatego tworzę wadliwy kod.
To całkiem normalne, że jeden model widoku tworzy jeden lub więcej innych modeli widoku. – Sheridan