CIMStandaloneTable.FieldDescriptions property allways return null in ArcGis Pro 3.0

978
8
Jump to solution
08-05-2022 05:31 AM
StephenCochrane
New Contributor III

I have this C# function to retrieve the CIMFieldDefinitions from a standalone table. It worked fine in the Pro 2.9.x but after migrating to Pro 3.0 it seems that FieldDescriptions property on the CIMStandaloneTable class is always null.

 

public CIMFieldDescription[] GetCIMFieldDescriptions(StandaloneTable table)
{
CIMStandaloneTable cimTableDefinition = null;
QueuedTask.Run(() =>
{
cimTableDefinition = table.GetDefinition() as CIMStandaloneTable;
});
return cimTableDefinition.FieldDescriptions;
}

 

Is something wrong with this code? Or is this an issue for Pro 3.0?

0 Kudos
1 Solution

Accepted Solutions
Wolf
by Esri Regular Contributor
Esri Regular Contributor

I tried the following on both 2.9 and 3.0 and it seems to work (no  FieldDescription == null is returned):

protected override async void OnClick()
{
  var mapMembers = MapView.Active.Map.GetLayersAsFlattenedList().OfType<MapMember>();
  var result = await QueuedTask.Run<string>(() =>
  {
    StringBuilder sb = new StringBuilder();
    foreach (var mapMember in mapMembers)
    {
      sb.AppendLine($@"member: {mapMember.Name} is Standalone: {mapMember is StandaloneTable} is BasicFeatureLayer {mapMember is BasicFeatureLayer}");
      if (!(mapMember is StandaloneTable || mapMember is BasicFeatureLayer)) continue;
      var dispTable = mapMember as IDisplayTable;
      var fieldDescriptions = dispTable.GetFieldDescriptions();
      foreach (var field in fieldDescriptions)
      {
        field.IsVisible = true;
      }
      sb.AppendLine($@" => table: {dispTable.GetTable().GetName()} fields: {fieldDescriptions.Count}");
      dispTable.SetFieldDescriptions(fieldDescriptions);
    }
    return sb.ToString();
  });
  mapMembers = MapView.Active.Map.GetStandaloneTablesAsFlattenedList().OfType<MapMember>();
  result += await QueuedTask.Run<string>(() =>
  {
    StringBuilder sb = new StringBuilder();
    foreach (var mapMember in mapMembers)
    {
      sb.AppendLine($@"member: {mapMember.Name} is Standalone: {mapMember is StandaloneTable} is BasicFeatureLayer {mapMember is BasicFeatureLayer}");
      if (!(mapMember is StandaloneTable || mapMember is BasicFeatureLayer)) continue;
      var dispTable = mapMember as IDisplayTable;
      var fieldDescriptions = dispTable.GetFieldDescriptions();
      foreach (var field in fieldDescriptions)
      {
        field.IsVisible = true;
      }
      sb.AppendLine($@" => table: {dispTable.GetTable().GetName()} fields: {fieldDescriptions.Count}");
      dispTable.SetFieldDescriptions(fieldDescriptions);
    }
    return sb.ToString();
  });
  MessageBox.Show(result);
}

View solution in original post

0 Kudos
8 Replies
Wolf
by Esri Regular Contributor
Esri Regular Contributor

I tried the following on both 2.9 and 3.0 and it seems to work (no  FieldDescription == null is returned):

protected override async void OnClick()
{
  var mapMembers = MapView.Active.Map.GetLayersAsFlattenedList().OfType<MapMember>();
  var result = await QueuedTask.Run<string>(() =>
  {
    StringBuilder sb = new StringBuilder();
    foreach (var mapMember in mapMembers)
    {
      sb.AppendLine($@"member: {mapMember.Name} is Standalone: {mapMember is StandaloneTable} is BasicFeatureLayer {mapMember is BasicFeatureLayer}");
      if (!(mapMember is StandaloneTable || mapMember is BasicFeatureLayer)) continue;
      var dispTable = mapMember as IDisplayTable;
      var fieldDescriptions = dispTable.GetFieldDescriptions();
      foreach (var field in fieldDescriptions)
      {
        field.IsVisible = true;
      }
      sb.AppendLine($@" => table: {dispTable.GetTable().GetName()} fields: {fieldDescriptions.Count}");
      dispTable.SetFieldDescriptions(fieldDescriptions);
    }
    return sb.ToString();
  });
  mapMembers = MapView.Active.Map.GetStandaloneTablesAsFlattenedList().OfType<MapMember>();
  result += await QueuedTask.Run<string>(() =>
  {
    StringBuilder sb = new StringBuilder();
    foreach (var mapMember in mapMembers)
    {
      sb.AppendLine($@"member: {mapMember.Name} is Standalone: {mapMember is StandaloneTable} is BasicFeatureLayer {mapMember is BasicFeatureLayer}");
      if (!(mapMember is StandaloneTable || mapMember is BasicFeatureLayer)) continue;
      var dispTable = mapMember as IDisplayTable;
      var fieldDescriptions = dispTable.GetFieldDescriptions();
      foreach (var field in fieldDescriptions)
      {
        field.IsVisible = true;
      }
      sb.AppendLine($@" => table: {dispTable.GetTable().GetName()} fields: {fieldDescriptions.Count}");
      dispTable.SetFieldDescriptions(fieldDescriptions);
    }
    return sb.ToString();
  });
  MessageBox.Show(result);
}
0 Kudos
CharlesMacleod
Esri Regular Contributor

Hi Stephen, use IDisplayTable.GetFieldDescriptions() and not the field descriptions off the CIM and u will be good to go (see Wolf's code above).

The CIM is optimized to only store  field descriptions if they have been (previously) modified, otherwise they are null. This is also true for feature layers (not just standalone tables). Whereas, field descriptions will always be provisioned from the IDisplayTable - and never null - regardless of whether they have been modified or not.

It could be that your CIM code worked previously because the table field descriptions had been modified at some point after it was added to a map.

0 Kudos
StephenCochrane
New Contributor III

Hi Charles & Wolf

Thanks for your answers. I was assigned to a different project for a while, but now I have returned to this and have been testing solution from Wolf. The code seems work as intended but there is one annoying issue.

I am doing some custom buttons where the user can change which columns are shown in ArcGIS Pro. In the code I use FieldDescription.IsVisible prorperty to change this.

My issue now, is that if the table window is open and I change the IsVisible to false for any given column then the window is automatically refreshed (and the column is removed for the view). However, when changing the IsVisible property back to True there is no automatically refresh and the column does not reappear. If I look in the fields view the Visible checkboxes are set according to my changes in the button implementation. So, it is only the updating of the of the table window that is broken (and only for columns that are change to visible)

I can add that I have tried a manual refresh on the table window (the refresh icon at the button of the window) in the situations where visible columns are not shown. This does not solve the problem. But if I completely close the table window an reopen it all columns are shown correctly.

Could this be a bug? Or do you have any other suggestions?

 

Best regards

0 Kudos
CharlesMacleod
Esri Regular Contributor

stephen, i cannot repro on 3.0

this is the OnClick code i used in my test button - it is toggling a (random) field's visibility on a standalone table and each time the table view refreshes to show/hide the particular field

protected override void OnClick() {
  var table = MapView.Active.Map.GetStandaloneTablesAsFlattenedList()
                       .FirstOrDefault(t => t.Name == "GreatLakes_Table");
  QueuedTask.Run(() =>
  {
    var fld_descs = table.GetFieldDescriptions();
    var fld_desc = fld_descs.FirstOrDefault(f => f.Alias == "CScode");
    fld_desc.IsVisible = !fld_desc.IsVisible;
    table.SetFieldDescriptions(fld_descs);
  });
}

 

0 Kudos
StephenCochrane
New Contributor III

Hi Charles

Thanks for your quick reply. I agree that your code is running fine, and I think my problem is related to the fact that I am also tampering with field aliases. Basically, I have a table with two fields "MyAtt_Scn0" and "MyAtt_Scn1". I want to display only one of these fields with the alias name being just “MyAtt”. Which one to show is dependent on a user selection. I have done quick code sample that reproduces the problem I saw (this implementation just toggles between the selections when the button is pressed):

		private int _scnId = 0;
		protected override void OnClick()
		{
			_scnId = (_scnId == 0) ? 1 : 0; // simple way too toggle between 0 and 1 each time the button pressed

			var table = MapView.Active.Map.GetStandaloneTablesAsFlattenedList()
													 .FirstOrDefault(t => t.Name == "MyScnarioTable");
			QueuedTask.Run(() =>
			{
				var fld_descs = table.GetFieldDescriptions();
				foreach (var fld_desc in fld_descs)
				{
					if (fld_desc.Name == "MyAtt_Scn0")
					{
						fld_desc.Alias = _scnId == 0 ? "MyAtt" : "MyAtt_Scn0";
						fld_desc.IsVisible = (_scnId == 0);
					}
					if (fld_desc.Name == "MyAtt_Scn1")
					{
						fld_desc.Alias = _scnId == 1 ? "MyAtt" : "MyAtt_Scn1";
						fld_desc.IsVisible = (_scnId == 1);
					}
				};
				table.SetFieldDescriptions(fld_descs);
			});
		}

Maybe I should try to alter the field aliases first and applied that. Then change the visibility afterwards.

0 Kudos
CharlesMacleod
Esri Regular Contributor

So I think this is a bug. I notice that if I change the alias when the field is _not_ visible in the Table View the table view does not refresh correctly (when I set the field back to being visible).

That said, as a workaround, do you have to actually dynamically change the alias name? Instead, can you set both field alias' to be "MyAtt" upfront and then simply toggle visibility between the two based on whatever is your underlying criteria?....the end result being the same - that only one or the other is shown.

That worked for me - I set two columns to have the same alias upfront and then toggled visibility between one and then the other. The view correctly switched between the two columns, each w the same alias name, as their underlying visibility was toggled.

0 Kudos
StephenCochrane
New Contributor III

Thanks again. Your answer is much appreciated.

The case I sent yesterday was quite simplified. The code is going run in scenario management plugin we are doing and will contain a dynamical number of _ScnXX columns (and we have multiple attributes with the _ScnXX postfix). Based on your answer I think the best work around for us right now is to do the following: Each time the view is altered by the user we start by setting all fields visible. Then we setup the view according to user selection. So, in principle:

		private int _scnId = 0;
		protected override void OnClick()
		{
			_scnId = (_scnId == 0) ? 1 : 0; // simple way too toggle between 0 and 1 each time the button is pressed

			var table = MapView.Active.Map.GetStandaloneTablesAsFlattenedList()
													 .FirstOrDefault(t => t.Name == "MyScenarioTable");
			QueuedTask.Run(() =>
			{
				var fld_descs = table.GetFieldDescriptions();
				foreach (var fld_desc in fld_descs)
				{
					fld_desc.IsVisible = true;
				}
				table.SetFieldDescriptions(fld_descs);
				fld_descs = table.GetFieldDescriptions();
				foreach (var fld_desc in fld_descs)
				{
					if (fld_desc.Name == "MyAtt_Scn0")
					{
						fld_desc.Alias = _scnId == 0 ? "MyAtt" : "MyAtt_Scn0";
						fld_desc.IsVisible = (_scnId == 0);
					}
					if (fld_desc.Name == "MyAtt_Scn1")
					{
						fld_desc.Alias = _scnId == 1 ? "MyAtt" : "MyAtt_Scn1";
						fld_desc.IsVisible = (_scnId == 1);
					}
				};
				table.SetFieldDescriptions(fld_descs);
				fld_descs = table.GetFieldDescriptions();
			});
		}

The downside of this approach is that the table window is “refreshed” two times each time the user changes the selection. So, an ArcGIS Pro bugfix would still be a good improvement. Can you report the bug or should I be involved? And in case you report it can I get a bug number in order to track it? And finally, would you venture a guess for the time frame for such a bugfix?

0 Kudos
CharlesMacleod
Esri Regular Contributor

I'll keep u posted. An internal bug issue has been created. It is also an issue with the UI too, fyi.

If you want a BUG number to track then if u submit an issue to tech support, they will give u an external number that would get linked with the internal bug for tracking purposes. Otherwise, I'll update this thread when the bug is fixed. As currently, that would be 3.1, otherwise 3.2. Thanks Stephen

0 Kudos