¿Cómo puedo pasar parámetros de un parentViewModel a mi ViewModel?

I have an "open" command where the user can chose a file. When the file is chosen (and therefore I have got the filepath as a string) I get a new instance of my DataView (Con la NonShared y CreationPolicy attributes) out of the CompositionContainer and display it in a specific region. My DataView obtiene su DataViewModel via DI. Now my problem is how do I pass the selected filepath to the NUEVO (created after file is chosen) ViewModel?

My first approach seemed clever and worked as long as I only created one View. But since I create multiple views (Tabs) the following approach does NOT work because I cant compose the same value more than once.

if (fileDialog.ShowDialog() == true)
{               
    Container.ComposeExportedValue("FilePath", fileDialog.FileName);
    IRegion contentRegion = regionManager.Regions[Regions.CONTENT];
    contentRegion.Add(Container.GetExportedValue<IDataView>(), null, true);
} 

[ImportingConstructor]
public DataViewModel(IRegionManager regionManager, 
    [Import("FilePath")] string filePath)
{ }

Is there any other way to inject / pass my string parameter to the viewmodel?

preguntado el 27 de agosto de 11 a las 22:08

2 Respuestas

I think you need to use a service for opening files rather than exporting values through MEF.

If you had a common service that all your ViewModels used, they could simply import your service and call an OpenFile() method.

Tengo una MVVM open source project, that has a quick example of doing this. See the templates example aquí.

Also check the top answer aquí, they have another implementation.

contestado el 23 de mayo de 17 a las 15:05

Thats what I also thought about, but then I came to the problem that the View and the ViewModel do not exist when the user choses a file. They are created when the user has successfully chosen a file. A solution would be to create the View and its ViewModel when the user clicks "open" and if he cancels the filedialog, destroy the View and ViewModel, but that sounds awkward. - Sebastián

If you are truly following MVVM, then you will have an appropriate View and ViewModel for each screen (or section) in your application. If the opening of a file displays a new window after choosing the file, then this work would be done in a "parent" ViewModel and you would not need to create (or import with MEF) this "child" ViewModel until the file is chosen. - jonathanpeppers

The work is actually done in the "parent" viewmodel, but the data that must be displayed (related on the chosen file) must be displayed in a new view, and either way i need to pass a) the information of the file or b) the data that is generated due to the chosen file to the new view, otherwise the view does not know what to display (to get a better understanding maybe watch how the open file process in f.e. Notepadd++ is done. You press Open, you choose a file, then press ok, and then a new tab with the file data is displayed (The tab is the view i want to create). - Sebastián

Your new tab just needs to expose a string property that the parent ViewModel would set with the file name. - jonathanpeppers

Injecting a dependency through a Views Datacontext (thats what I must do since my View creates the ViewModel -> View.DataContext.MyStringProperty = myString;) sounds awkward. When I have found a "clean" solution, I will edit my question with the solution. But thanks anyway - Sebastián

I always handled this kind of thing within a ViewModel

My ParentViewModel contendría una instancia del OpenFileViewModely cuando el ParentViewModel.SelectFileCommand gets executed, it calls something like OpenFileViewModel.SelectFile()

To get the selected file, I often subscribe to OpenFileViewModel.PropertyChanged and listen for change events on the FileName property, or sometimes I'll have an overwritable ProcessFile method which I can hook up an event to that will fire when a file gets selected.

Al OpenFileViewModel.SelectFilemethod usually looks something like this

private void SelectFile()
{
    var dlg = new OpenFileDialog();
    dlg.DefaultExt = this.Extension;
    dlg.Filter = this.Filter;

    if (dlg.ShowDialog() == true)
    {
        var file = new FileInfo(dlg.FileName);
        FileName = file.FullName;

        if (ProcessFileDelegate != null)
            ProcessFileDelegate()
    }
}

y mi ParentViewModel will often contain code that looks something like this:

public ParentViewModel()
{
    this.OpenFileDialog = new OpenFileViewModel();
    this.OpenFileDialog.PropertyChanged += OpenFileDialog_PropertyChanged;
    this.OpenFileDialog.ProcessFileDelegate = ProcessFile;
}

Respondido 29 ago 11, 17:08

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.