After 2 years of learning and automating stuff using Python I am now revisiting Pro .net addins because I wasn't happy with the rather clunky UI options when I needed user input.
So what I have is two listboxes where the selected item in the first listbox defines what shows up in the second listbox. This would be easily accomplished using bindings, the rub is that to flll the second listbox I need to use and async function, which I can't call in the first listbox's SelectedItem setter. As a workaround, in the setter I call another syncronous function that runs the async function.
This works, but somehow my gut is telling me this is cheating and not the proper way to do this, and I'm not sure if this could potentially stall the UI thread if my database gets bigger.
Could somebody tell me if there's a better way to do this?
Below is the ViewModel code, the DAML would be pretty obvious.
using ArcGIS.Core.Data;
using ArcGIS.Core.Geometry;
//using ArcGIS.Core.Internal.CIM;
using ArcGIS.Desktop.Catalog;
using ArcGIS.Desktop.Core;
using ArcGIS.Desktop.Editing;
using ArcGIS.Desktop.Extensions;
using ArcGIS.Desktop.Framework;
using ArcGIS.Desktop.Framework.Contracts;
using ArcGIS.Desktop.Framework.Dialogs;
using ArcGIS.Desktop.Framework.Threading.Tasks;
using ArcGIS.Desktop.KnowledgeGraph;
using ArcGIS.Desktop.Layouts;
using ArcGIS.Desktop.Mapping;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
namespace BVES
{
internal class PSPSpaneViewModel : DockPane
{
private const string _dockPaneID = "BVES_PSPSpane";
private ObservableCollection<string> _lstTypes;
private ObservableCollection<string> _lstDevices;
Dictionary<String, ObservableCollection<String>> dctDevices = new();
public ICommand BtnUpdate_Click_Command { get; set; }
protected PSPSpaneViewModel()
{
InitializeDockPane();
}
private async void InitializeDockPane()
{
ObservableCollection<string> myTypes = new();
await QueuedTask.Run(() => GetTypes(myTypes));
LstTypes = myTypes;
//await QueuedTask.Run(() => GetDevices(dctDevices));
SelType = "CircuitBreaker";
}
/// <summary>
/// Show the DockPane.
/// </summary>
internal static void Show()
{
DockPane pane = FrameworkApplication.DockPaneManager.Find(_dockPaneID);
if (pane == null)
return;
pane.Activate();
}
//private int deviceCount;
public ICommand CmdSelectDevice
{
get
{
return new RelayCommand(() =>
{
if (_selDevice != null)
{
CountCustomers(_selDevice);
}
});
}
}
public async void CountCustomers(String strDevice)
{
ObservableCollection<String> lstCustomers = new();
await QueuedTask.Run(() => GetCustomers(lstCustomers, _selDevice));
MessageBox.Show(lstCustomers.Count + " Customers for device " + SelDevice);
}
private string _GDBpath = "F:/BVES/";
public string GDBpath
{
get => _GDBpath;
set => SetProperty(ref _GDBpath, value);
}
/// <summary>
/// Text shown near the top of the DockPane.
/// </summary>
private string _heading = "PSPS";
public string Heading
{
get => _heading;
set => SetProperty(ref _heading, value);
}
private string _selType = "";
public string SelType
{
get => _selType;
//set => SetProperty(ref _selType, value);
set
{
_selType = value;
NotifyPropertyChanged("SelType");
updateDevicelist();
//if (dctDevices.ContainsKey(SelType))
//{
// LstDevices = dctDevices[SelType];
//}
}
}
private string _selDevice = "";
public string SelDevice
{
get => _selDevice;
//set => SetProperty(ref _selType, value);
set
{
_selDevice = value;
NotifyPropertyChanged("SelType");
ObservableCollection<String> lstCustomers = new();
//await QueuedTask.Run(() => GetCustomer(lstCustomers,_selDevice));
}
}
/// <summary>
/// List of device types bound to the Type listbox
/// </summary>
public ObservableCollection<String> LstTypes
{
get { return _lstTypes; }
set
{
_lstTypes = value;
NotifyPropertyChanged("LstTypes");
}
}
/// <summary>
/// List devices bound to the device listbox
/// </summary>
public ObservableCollection<string> LstDevices
{
get { return _lstDevices; }
set
{
//_lstDevices = value;
//NotifyPropertyChanged("LstDevices");
SetProperty(ref _lstDevices, value, () => LstDevices);
}
}
/* public bool GetTypesHard(ObservableCollection<String> inColl)
{
inColl.Add("Fuse");
inColl.Add("TripSaver");
inColl.Add("AutoRecloser");
inColl.Add("CircuitBreaker");
return true;
}
*/
/// <summary>
/// Get a list device types. To be run as a QueuedTask.
/// </summary>
public void GetTypes(ObservableCollection<String> MyTypes)
{
Geodatabase gdb_GisData = new Geodatabase(new FileGeodatabaseConnectionPath(new Uri(_GDBpath + "BVES_GIS_Data.gdb", UriKind.Absolute)));
Geodatabase gdb_Assets = new Geodatabase(new FileGeodatabaseConnectionPath(new Uri(_GDBpath + "BVES_Assets.gdb", UriKind.Absolute)));
Table tblPSPS = gdb_GisData.OpenDataset<Table>("tblPSPS");
QueryFilter qFilt = new QueryFilter();
qFilt.SubFields = "UpType";
qFilt.PrefixClause = "DISTINCT";
qFilt.PostfixClause = "";
string strType;
using (RowCursor rowCursor = tblPSPS.Search(qFilt))
{
while (rowCursor.MoveNext())
{
using (Row current = rowCursor.Current)
{
strType = (string)current["UpType"];
MyTypes.Add(strType);
}
}
}
}
/// <summary>
/// Get a list devices of the given type. To be run as a QueuedTask.
/// </summary>
public void GetDevices(ObservableCollection<String> lstDevices, String SelType)
{
//Dictionary<String, ObservableCollection<String>> _dctDevices = new();
Geodatabase gdb_GisData = new Geodatabase(new FileGeodatabaseConnectionPath(new Uri(_GDBpath + "BVES_GIS_Data.gdb", UriKind.Absolute)));
Geodatabase gdb_Assets = new Geodatabase(new FileGeodatabaseConnectionPath(new Uri(_GDBpath + "BVES_Assets.gdb", UriKind.Absolute)));
Table tblPSPS = gdb_GisData.OpenDataset<Table>("tblPSPS");
QueryFilter qFilt = new QueryFilter();
qFilt.SubFields = "UpDevice";
qFilt.PrefixClause = "DISTINCT";
qFilt.PostfixClause = "";
string strDevice;
qFilt.WhereClause = "UpType = '" + SelType + "'";
//ObservableCollection<string> tmpColl = new ObservableCollection<string>();
lstDevices.Clear();
using (RowCursor rowCursor = tblPSPS.Search(qFilt))
{
while (rowCursor.MoveNext())
{
using (Row current = rowCursor.Current)
{
strDevice = (string)current["UpDevice"];
lstDevices.Add(strDevice);
}
}
}
}
/// <summary>
/// Run a QueuedTask to get device names and populate the device list
/// </summary>
public async void updateDevicelist()
{
ObservableCollection<String> lstDevs = new();
await QueuedTask.Run(() => GetDevices(lstDevs, _selType));
LstDevices = lstDevs;
}
/// <summary>
/// Count downstream customers given a device name.
/// </summary>
public void GetCustomers(ObservableCollection<String> MyDevices, String strDevice)
{
//Dictionary<String, ObservableCollection<String>> _dctDevices = new();
Geodatabase gdb_GisData = new Geodatabase(new FileGeodatabaseConnectionPath(new Uri(_GDBpath + "BVES_GIS_Data.gdb", UriKind.Absolute)));
Geodatabase gdb_Assets = new Geodatabase(new FileGeodatabaseConnectionPath(new Uri(_GDBpath + "BVES_Assets.gdb", UriKind.Absolute)));
Table tblPSPS = gdb_GisData.OpenDataset<Table>("tblPSPS");
QueryFilter qFilt = new QueryFilter();
qFilt.SubFields = "PREM_ID";
qFilt.PrefixClause = "";
qFilt.PostfixClause = "";
qFilt.WhereClause = "UpDevice = '" + strDevice + "'";
String strCustomer;
using (RowCursor rowCursor = tblPSPS.Search(qFilt))
{
while (rowCursor.MoveNext())
{
using (Row current = rowCursor.Current)
{
strCustomer = (string)current["UpDevice"];
MyDevices.Add(strCustomer);
}
}
}
}
/* public void GetDevicesAll(Dictionary<String, ObservableCollection<String>> _dctDevices)
{
//Dictionary<String, ObservableCollection<String>> _dctDevices = new();
Geodatabase gdb_GisData = new Geodatabase(new FileGeodatabaseConnectionPath(new Uri(_GDBpath + "BVES_GIS_Data.gdb", UriKind.Absolute)));
Geodatabase gdb_Assets = new Geodatabase(new FileGeodatabaseConnectionPath(new Uri(_GDBpath + "BVES_Assets.gdb", UriKind.Absolute)));
Table tblPSPS = gdb_GisData.OpenDataset<Table>("tblPSPS");
QueryFilter qFilt = new QueryFilter();
qFilt.SubFields = "UpDevice";
qFilt.PrefixClause = "DISTINCT";
qFilt.PostfixClause = "";
string strDevice;
foreach (string itmType in LstTypes)
{
qFilt.WhereClause = "UpType = '" + itmType + "'";
ObservableCollection<string> tmpColl = new ObservableCollection<string>();
using (RowCursor rowCursor = tblPSPS.Search(qFilt))
{
while (rowCursor.MoveNext())
{
using (Row current = rowCursor.Current)
{
strDevice = (string)current["UpDevice"];
tmpColl.Add(strDevice);
}
}
_dctDevices.Add(itmType, tmpColl);
}
}
}
*/
/// <summary>
/// Button implementation to show the DockPane.
/// </summary>
}
internal class PSPSpane_ShowButton : Button
{
protected override void OnClick()
{
PSPSpaneViewModel.Show();
}
}
}