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
}
精彩评论