Dies ist eine ziemlich lange Frage, also bitte bitte mit mir.Caliburn.Micro verschachtelt ViewModels Best Practice
Derzeit entwickle ich ein kleines Tool, das mir helfen soll, die unzähligen Charaktere in meinen Geschichten zu verfolgen.
Das Tool führt Folgendes aus:
- Legen Sie die Zeichen, die zur Zeit als json auf der Festplatte und speichert sie in einer Liste gespeichert werden, die in der Shell über eine List-Box präsentiert wird.
- Wenn der Benutzer dann ein Zeichen öffnet, öffnet die Shell, die eine
Conductor<Screen>.Collection.OneActive
ist, eine neueCharacterViewModel
, die vonScreen
abgeleitet wird. - Die
Character
erhält das Zeichen, das über das NachrichtensystemIEventAggregator
geöffnet wird. - Die
CharacterViewModel
hat außerdem verschiedene Eigenschaften, die unter ViewModels sind, die an verschiedene Unteransichten binden.
Und hier ist mein Problem: Zur Zeit habe ich die Unterviewmodels manuell initialisiert werden, wenn der ChracterViewModel
initialisiert wird. Aber das hört sich für mich fischig an und ich bin mir ziemlich sicher, dass es einen besseren Weg dafür gibt, aber ich kann nicht sehen, wie ich es tun soll. Hier
ist der Code des 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;
}
}
für die Fertigstellung Sake ich Ihnen auch eine der Unterviewmodels geben. Die anderen haben keine Bedeutung, da sie auf die gleiche Weise strukturiert sind, nur verschiedene Aufgaben ausführen.
/// <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);
}
}
}
Ich las bereits in auf Screens, Conductors and Composition, IResult and Coroutines und den Rest der Dokumentation abgeschöpft, aber irgendwie kann ich nicht finden, was ich suche.
// bearbeiten: Ich sollte den Code erwähnen, ich habe funktioniert gut. Ich bin einfach nicht damit zufrieden, da ich denke, ich verstehe das Konzept von MVVM nicht ganz richtig und mache daher fehlerhaften Code.
Es ist ganz normal, dass ein Ansichtsmodell ein oder mehrere andere Ansichtsmodelle instanziiert. – Sheridan