0

Hello I am using a System.Windows.Forms.FolderBrowserDialog in my WPF application to select folders in users computer. The selected folder is displayed in a TextBox and also is validated in the view model.

I am trying to display invalid folder Error Template message below the TextBox for the following scenario:

  1. If the folder does not exist and not accessible.
  2. if the user selects a folder that is a system folder. For this example, I hard coded the value as @"c:\windows\boot".

What I am noticing is: If I type a folder that does not exist, I will get the binding exception which allows me to set the error template.

But if I select a drive that the user does not have access or I select the @"c:\windows\boot" I will get an exception that is either caught at the App.xaml unhandle exception or if u have a try catch (where the folder is set) it will be caught there. How can I have this as a binding exception? Before I decide to just leave it as a try catch I wanted to understand if there is anyway I can have it as a binding exception (which saves a click!).

Here is the code:

public class MainWindowViewModel : INotifyPropertyChanged
    {
        public MainWindowViewModel()
        {
        }

        private string _folderName;
        public string FolderName
        {
            get { return _folderName; }
            set
            {
                _folderName = value;

                if (!string.IsNullOrEmpty(_folderName))
                    InvalidValidFolder();

                if (!string.IsNullOrEmpty(_folderName))
                    ValidateFolder();

                OnPropertyChanged("FolderName");
            }
        }

        private void ValidateFolder()
        {
            if (!Directory.Exists(FolderName))
                throw new Exception("Folder does not exist");
        }

        private void InvalidValidFolder()
        {
            if (FolderName.ToLower() == @"c:\windows\boot")
                throw new Exception("This folder is restricted.");
        }

        public event PropertyChangedEventHandler PropertyChanged;

        public void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }

    }

I just have MainWindow and MainWindowViewModel.

<DockPanel>
        <Grid DockPanel.Dock="Top" Width="Auto" Margin="50">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>
            <TextBox x:Name="textBox" Text="{Binding FolderName, ValidatesOnExceptions=True, ValidatesOnDataErrors=True}" Margin="0,0,0,5" Grid.Column="0" />
            <Button Grid.Column="1"
                        Margin="5,0,5,0"
                        Width="35"
                        Content="..."
                        Click="LocationChoose_Click"/>
        </Grid>
        <Grid></Grid>
    </DockPanel>

Codebehind

public partial class MainWindow : Window
    {
        public MainWindowViewModel ViewModel {get; set;}
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = ViewModel = new MainWindowViewModel();
        }

        private void LocationChoose_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                FolderBrowserDialog folderDlg = new FolderBrowserDialog();
                folderDlg.ShowDialog();
                ViewModel.FolderName = folderDlg.SelectedPath;

            }
            catch (Exception ex)
            {
                System.Windows.MessageBox.Show(ex.Message);
            }
        }
    }
Anatoliy Nikolaev
  • 22,370
  • 15
  • 69
  • 68
isakavis
  • 773
  • 1
  • 12
  • 29

1 Answers1

0

Got the answer if anyone is interested.

I changed the code behind to:

private void LocationChoose_Click(object sender, RoutedEventArgs e)
{
    FolderBrowserDialog folderDlg = new FolderBrowserDialog();
    folderDlg.ShowDialog();
    //ViewModel.FolderName = folderDlg.SelectedPath;
    textBox1.Text = folderDlg.SelectedPath;
    BindingExpression exp = this.textBox1.GetBindingExpression(System.Windows.Controls.TextBox.TextProperty);
    exp.UpdateSource();
}

This treats it as a binding exception. Now I can apply my template. Thanks for your time.

isakavis
  • 773
  • 1
  • 12
  • 29
  • However, another question came to my mind. Is this code behind (above snippet) violating good principle of no code behind for MVVM? Where is the fine line of how much code behind we can have in MVVM? Had I used DelegateCommand of PRISM, I would not have access to the textbox. In that case what other solution I can have? – isakavis Mar 28 '13 at 19:27