0
votes

I have folder browser dialog that is bound to the SetterName

private void OnClick(object sender, RoutedEventArgs e)
        {

            var dialog = new FolderBrowserDialog();
            var result = dialog.ShowDialog();
            if (result == DialogResult.OK && AssociatedObject.DataContext != null)
            {
                var propertyInfo = AssociatedObject.DataContext.GetType().GetProperties(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public)
                    .Where(p => p.CanRead && p.CanWrite)
                    .First(p => p.Name.Equals(SetterName));

                string dirName = new DirectoryInfo(dialog.SelectedPath).Name;
                FolderName = dirName;
                _fileName = System.IO.Path.GetFileName(dirName);
                FileName = _fileName;
                propertyInfo.SetValue(AssociatedObject.DataContext, dialog.SelectedPath, null);
            }
        }

And I have the properties set in the ViewModel

public class CommonUseWindowViewModel:INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public Model New { get; set; }
        public ICommand Build { get; set; }
        public CommonUseWindowViewModel()
        {
            Build = new DelegateCommand(ClickedMethod);

        }

        protected async void ClickedMethod()
        {

            IsEnabled = false;
            var gdbName = FolderName;
            var styleFol = StyleName;
            var envArray = await QueuedTask.Run(() => Geoprocessing.MakeEnvironmentArray(overwriteoutput: true));
            var valueArray = await QueuedTask.Run(() => Geoprocessing.MakeValueArray(gdbName, styleFol));
            string toolPath = @"c:\staging\ProBaseMapBuilder\BasemapBuilder.tbx\BasemapCreator";
            var gpresult1 = await QueuedTask.Run(() => Geoprocessing.ExecuteToolAsync(toolPath, valueArray, envArray));
            MessageBox.Show("All Layers Have Been Added to The Map");
            IsEnabled = true;
        }
        private bool _isEnabled = true;
        public bool IsEnabled
        {
            get { return _isEnabled; }
            set
            {
                _isEnabled = value;
                OnPropertyChanged("IsEnabled");
            }
        }
        private string _folderName;
        public string ShortenedFolderName => Path.GetFileName(_folderName);
        public string FolderName
        {
            get { return _folderName; }
            set
            {
                _folderName = value;
                OnPropertyChanged("FolderName");
                OnPropertyChanged(nameof(ShortenedFolderName));
            }
        }

        private string _styleName;
        public string ShortenedStyleName => Path.GetFileName(_styleName);
        public string StyleName
        {
            get { return _styleName; }
            set
            {
                _styleName = value;
                OnPropertyChanged("StyleName");
                OnPropertyChanged(nameof(ShortenedStyleName));
            }
        }

        private void OnPropertyChanged(string propertyname)
        {
            OnPropertyChanged(new PropertyChangedEventArgs(propertyname));
        }

        private void OnPropertyChanged(PropertyChangedEventArgs args)
        {
            var handler = PropertyChanged;
            if (handler != null)
                handler(this, args);
        }

    }

I would like to move the properties to a Model class but when I do the folder dialog raises an error that there is no matching setter name. I think the problem comes not knowing how to bind this to the view. I am wondering if I am referencing namespace correctly in the view

        xmlns:FolderDialog="clr-namespace:BasemapCreator.Behaviors"
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
        xmlns:Behaviors="clr-namespace:ArcGIS.Desktop.Internal.Framework.Behaviors;assembly=ArcGIS.Desktop.Framework" x:Class="BasemapCreator.CommonUseWindow" 
        xmlns:DataContext="clr-namespace:BasemapCreator.Models"



<TextBox x:Name="gdbName" HorizontalAlignment="Left" Height="30" Margin="56,29,0,0"  Text="{Binding Model.FolderName, Mode=TwoWay}" VerticalAlignment="Top" Width="282" AllowDrop="True" Visibility="Hidden">

When I add the Model.FolderName to the text box binding I get the error coming from folder dialog.

here is my model

namespace BasemapCreator.Models
{
    public class Model:INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        private bool _isEnabled = true;
        public bool IsEnabled
        {
            get { return _isEnabled; }
            set
            {
                _isEnabled = value;
                OnPropertyChanged("IsEnabled");
            }
        }
        private string _folderName;
        public string ShortenedFolderName => Path.GetFileName(_folderName);
        public string FolderName
        {
            get { return _folderName; }
            set
            {
                _folderName = value;
                OnPropertyChanged("FolderName");
                OnPropertyChanged(nameof(ShortenedFolderName));
            }
        }

        private string _styleName;
        public string ShortenedStyleName => Path.GetFileName(_styleName);
        public string StyleName
        {
            get { return _styleName; }
            set
            {
                _styleName = value;
                OnPropertyChanged("StyleName");
                OnPropertyChanged(nameof(ShortenedStyleName));
            }
        }

        private void OnPropertyChanged(string propertyname)
        {
            OnPropertyChanged(new PropertyChangedEventArgs(propertyname));
        }

        private void OnPropertyChanged(PropertyChangedEventArgs args)
        {
            var handler = PropertyChanged;
            if (handler != null)
                handler(this, args);
        }

    }
}

I am using a viewmodel created from a button click Button Class

namespace BasemapCreator
{
    internal class ShowWindow : Button
    {
        private CommonUseWindow _dlg = null;
        protected override void OnClick()
        {
            if (_dlg != null) return;
            _dlg = new CommonUseWindow();
            _dlg.Closing += ProWin_Closing;
            _dlg.Owner = FrameworkApplication.Current.MainWindow;
            _dlg.Show();
        }
        void ProWin_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            _dlg = null;
        }
    }
}

In the code behind for the view I have the DataContext set to the viewModel, can I change it and still use the viewmodel?

using ArcGIS.Desktop.Framework.Controls;
using BasemapCreator.ViewModels;
using System;
using System.Windows;
using BasemapCreator.Models;

namespace BasemapCreator
{
    /// <summary>
    /// Interaction logic for CommonUseWindow.xaml
    /// </summary>
    public partial class CommonUseWindow : ProWindow
    {
        private CommonUseWindowViewModel _vm = new CommonUseWindowViewModel();
        public CommonUseWindow()
        {
            InitializeComponent();
            this.DataContext = _vm;
        }

    }
}

Here is the code behind for the view,

1
How and where do you set the DataContext of the behavior/view? Could you add that part of the code in? I'm guessing that's where the problem is. - Filip Milovanović
I am using a viewmodel, I don't think the data context is set. - Gary Lester
That means that the viewmodel is the data context (as expected). It is set; you can see yourself that your FolderBrowserDialog updates a property on the data context via reflection. I problem is most likely that you are moving the properties to the model, but the data context is still the viewmodel, so it tries to find them there. So whatever piece of code or framework mechanism sets the viewmodel needs to be changed. - Filip Milovanović

1 Answers

0
votes

In your MainWindow code behind...

using YourProjectName.FolderName;

Then in the MainWindow constructor

InitializeComponent();
//usually this is the only code behind in a view
DataContext = new ClassName();