1

I have a text box for file name with path. After user locates a file using OpenFileDialog, this text box should be populated with filename. This text should also work when user enters filename with path directly instead of selecting from file dialog box.

Since I am learning MVVM, I am getting hard time to figure out how to update text box with filename/path. I tried everything i can think of.

I was expecting onPropertyChanged(“FilenameWithPath”) should take care this issue. Can somebody show me how to deal with this issue?

See code below

FileBrowseView.xaml

<TextBox  Height="23" HorizontalAlignment="Left" Margin="113,22,0,0" 
               Name="txtFilenameWithPath" 
               Text="{Binding Path=FilenameWithPath, 
               UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"
               VerticalAlignment="Top" Width="300" />
<Button 
        Content="Browse..." 
        Height="30" 
        HorizontalAlignment="Left" 
        Margin="433,20,0,0" 
        Name="btnBrowse" 
        VerticalAlignment="Top"
        Width="142" 
        Command="{Binding Path=BrowseCommand}"  />

FileBrowseView.xaml.cs

public partial class FileBrowseView : Window
{
    public FileBrowseView()
    {
        InitializeComponent();
        DataContext = new FileBrowseViewModel();
    }


}

FileBrowseModel

public class FileBrowseModel
{
  private string _filenameWithPath = string.Empty;
    public string FilenameWithPath
    {
        get { return _filenameWithPath; }
        set
        {
            if (value == _filenameWithPath)
                return;
            else
                _filenameWithPath = value;
        }
    }

}

FileBrowseViewModel

public class FileBrowseViewModel  : INotifyPropertyChanged 
{   
  private string _filenameWithPath = string.Empty;
  public string FilenameWithPath
  {
        get { return _filenameWithPath; }
        set
        {
            if (value == _filenameWithPath)
                return;
            else
                _filenameWithPath = value;
            OnPropertyChanged("FilenameWithPath"); 
        }
    }

    private ICommand _browseCommand;
    public ICommand BrowseCommand
    {
        get
        {
            if (_browseCommand == null)
                _browseCommand = new DoBrowse();
            return _browseCommand;
        }
        set
        {
            _browseCommand = value;
            OnPropertyChanged("FilenameWithPath"); 
        }
    }


    private class DoBrowse : ICommand
    {
        public bool CanExecute(object parameter) { return true; }
        public event EventHandler CanExecuteChanged;
        public void Execute(object parameter)
        {
            var filedialog = new System.Windows.Forms.OpenFileDialog();
            DialogResult fresult = filedialog.ShowDialog();

            if (fresult == System.Windows.Forms.DialogResult.OK)
            {
                 FilenameWithPath = filedialog.FileName;
                //I am trying to assign value i got from OpenFileDialog to 
                // FilenameWithPath property
                //complier says "Cannot access non static member of outer type 
                   'MyProject.FileBrowseViewModel' via 
                  nested type 'MyProject.FileBrowseViewModel.DoBrowse

                onPropertyChanged(“FilenameWithPath”);                    
            }
        }
    }

   public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}
1
  • 1
    I would suggest using Microsoft.Win32.OpenFileDialog and not System.Windows.Forms.OpenFileDialog() as suggested by MSDN. Commented Aug 22, 2011 at 20:02

3 Answers 3

1

You just need to set FileNameWithPath in your command's Execute function. And the setter for FileNameWithPath ought to be calling OnPropertyChanged. You shouldn't have to call that from your command's Execute function.

Sign up to request clarification or add additional context in comments.

Comments

0

EDIT: Make sure that you are setting your data context to be the viewmodel and not the model since both have FilenameWithPath properties. If you were doing this the bind wouldn't fail because there is still a property to bind to. Otherwise:

Make the following changes:

public string FilenameWithPath
{
   get { return _filenameWithPath; }
   set
   {
       if (value == _filenameWithPath)
           return;
       else
       {
           _filenameWithPath = value;
           OnPropertyChanged("FilenameWithPath");
       }
   }
}

and

if (fresult == System.Windows.Forms.DialogResult.OK)
{
    FilenameWithPath = filedialog.FileName;
}

This should fix your problem. Additionally, consider changing which dialog box you use since this is WPF (as suggested in my comment).

1 Comment

I could not make it work. I have restated the issue on my posting.
0

Finally I am able to resolve this issue by adding new class called RelayCommand. I have modified the get block of _browseCommand use relay command as below.

private ICommand _browseCommand;
public ICommand BrowseCommand
{
  get{
    if (_browseCommand == null){
        _browseCommand = new RelayCommand(
                                         a => this.DoBrowseFolder(),
                                         p => this.CheckCondition());
    }

    return _browseCommand;
   }

    set
    {   _browseCommand = value;
        OnPropertyChanged("FilenameWithPath");
    }
   }


    public bool CheckCondition () {
    //Check condition here if needed        
        return true;
    }


    private void DoBrowseFolder(){
        var filedialog = new System.Windows.Forms.OpenFileDialog();
        DialogResult fresult = filedialog.ShowDialog();

        if (fresult == System.Windows.Forms.DialogResult.OK)
        {
            FilenameWithPath = filedialog.FileName;
            OnPropertyChanged("FilenameWithPath ");
        }

    }

Relay Command Class

public class RelayCommand : ICommand
{

    #region Fields
    readonly Action<object> _execute;
    readonly Predicate<object> _canExecute;
    #endregion // Fields

    #region Constructors      
    public RelayCommand(Action<object> execute, Predicate<object> canExecute){
        if (execute == null)             
            throw new ArgumentNullException("execute");          
        _execute = execute;         
        _canExecute = canExecute;     
    }     

    #endregion // Constructors      
    #region ICommand Members      
    [DebuggerStepThrough]     
    public bool CanExecute(object parameter)     {         
        return _canExecute == null ? true : _canExecute(parameter);     
    }      

    public event EventHandler CanExecuteChanged     
    {         
        add { CommandManager.RequerySuggested += value; }         
        remove { CommandManager.RequerySuggested -= value; }     
    }      

    public void Execute(object parameter)     {         
        _execute(parameter);     
    }      
    #endregion // ICommand Members      
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.