1

I'm opening a dialog in my view in response to a button click. I have a file class with the filePath property like so:

FileClass.cs

    private string _filePath;

    public string FilePath
    {
        get { return _filePath; }
        set 
        { 
            _filePath = value;
            OnPropertyChanged();
        }
    }

I create an instance in my viewModel:

viewmodel

    public MyFile myFile;
    public ViewModel()
    {
        myFile = new MyFile();
    }

The problem is when I try to use the property in the view:

            if (openFileDialog.ShowDialog() == true)
            {
                filePath = openFileDialog.FileName;

                (this.DataContext as ViewModel)?.myFile.FilePath = filePath; // error

            }

Why can't I do this?

sanya
  • 111
  • 11

1 Answers1

1

If you read the error it'll tell you that (this.DataContext as ViewModel)?.myFile.FilePath isn't an l-value. It's also non-sense.

Use this instead:

((ViewModel)DataContext).myFile.FilePath = filePath;

Of course, your setup breaks both MVVM guidelines and .Net naming and field conventions, but to each his own.

Blindy
  • 65,249
  • 10
  • 91
  • 131
  • How does this break MVVM? I was literally following this answer https://stackoverflow.com/questions/1043918/open-file-dialog-mvvm Solution 1 – sanya Apr 28 '22 at 00:31
  • 1
    Your view is changing the view-model properties (actually not even properties, just random public fields). You can *literally* follow anything you want, this is not MVVM. – Blindy Apr 28 '22 at 00:36
  • how is FilePath not a property? Can you explain exactly why am I breaking MVVM with this instead of "do whatever you like"? – sanya Apr 28 '22 at 00:38
  • 1
    I just told you, and I quote, "Your view is changing the view-model properties". In fact, here's a rule for you: any time you find yourself casting `DataContext` to anything, you have failed. The code that opens the open file dialog box should be called from the view model through a dependency injected dialog service, not called from a view. Also I don't know how to answer your question about properties, if you can't read that `public MyFile myFile;` is a public field. – Blindy Apr 28 '22 at 00:40
  • clearly you have not read the answer I linked... – sanya Apr 28 '22 at 00:42
  • I aprreciate your answer but look at what you're saying, calling the openDialogView from the ViewModel. This is dependency hiding, since you're moving the UI logic to another class (or service as you said) which is still controlled by the viewmodel and MVVM dictates that UI logic should be handled in the view. See https://stackoverflow.com/a/64861760/18754488 . But anyway since you're not willing to go through such "garbage" even though it carefully dismantles your argument, I'll just accept your answer – sanya Apr 28 '22 at 00:52
  • 1
    "carefully dismantles your argument" you aren't yet equipped to determine that. And it doesn't hide anything, the whole purpose of a dialog service is to be mockable in unit tests. What you wrote isn't unit testable, because the basic functionality of setting that file path actually is tied to opening a dialog *from another dialog*. An encapsulated view model can be unit tested from start to end by just providing a dialog service implementation that allows passing strings to the open file dialog request. – Blindy Apr 28 '22 at 00:57
  • 1
    Having the OpenDialog stuff in the view's code behind is okay, because it is UI-centric. The things that don't match too nicely with MVVM is `myFile` being a public field. It should also be a property. Moreover, if it was pure MVVM, you would not assign the file path to a field of the DataContext cast. But rather to a control property (TextBox/TextBlock Text for example), and let data binding do the View<->VM sync. – lidqy Apr 28 '22 at 01:03
  • "Having the OpenDialog stuff in the view's code behind is okay, because it is UI-centric" -- does the same logic apply to showing progress dialogs, message boxes or other various popups? I don't even believe "it's UI-centric" is an excuse for it, the purpose of the view model is to drive your view, it's UI-centric by definition and it should handle this. – Blindy Apr 28 '22 at 14:35