开发者

updating text with filename with path via OpenFileDialog using MVVM and WPF

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 P开发者_运维技巧ath=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));
    }
}


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.


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).


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      
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜