protected AbstractTableDataSourceFindUsagesContext( StreamingFindUsagesPresenter presenter, IFindAllReferencesWindow findReferencesWindow, ImmutableArray <AbstractCustomColumnDefinition> customColumns, bool includeContainingTypeAndMemberColumns, bool includeKindColumn) { presenter.AssertIsForeground(); Presenter = presenter; _findReferencesWindow = findReferencesWindow; TableControl = (IWpfTableControl2)findReferencesWindow.TableControl; TableControl.GroupingsChanged += OnTableControlGroupingsChanged; // If the window is closed, cancel any work we're doing. _findReferencesWindow.Closed += OnFindReferencesWindowClosed; DetermineCurrentGroupingByDefinitionState(); Debug.Assert(_findReferencesWindow.Manager.Sources.Count == 0); // Add ourselves as the source of results for the window. // Additionally, add applicable custom columns to display custom reference information _findReferencesWindow.Manager.AddSource( this, SelectCustomColumnsToInclude(customColumns, includeContainingTypeAndMemberColumns, includeKindColumn).ToReadOnlyCollection()); // After adding us as the source, the manager should immediately call into us to // tell us what the data sink is. Debug.Assert(_tableDataSink != null); // Initialize custom column states at start of the FAR query. _customColumnTitleToStatesMap = GetInitialCustomColumnStates(findReferencesWindow.TableControl.ColumnStates, customColumns); // Now update the custom columns' state/visibility in the FAR window. // Note that the visibility of the custom column(s) can change only at two possible places: // 1. FAR query start, i.e. below invocation to SetColumnStates and/or // 2. First reference result which has a non-default custom column value // (UpdateCustomColumnVisibility method below). // Also note that the TableControl.SetColumnStates is not dependent on order of the input column states. TableControl.SetColumnStates(_customColumnTitleToStatesMap.Values); }
public TableDataSourceFindUsagesContext( StreamingFindUsagesPresenter presenter, IFindAllReferencesWindow findReferencesWindow, string referenceName, ImmutableArray <AbstractFindUsagesCustomColumnDefinition> customColumns) { Microsoft.VisualStudio.Shell.ThreadHelper.ThrowIfNotOnUIThread(); ReferenceName = referenceName; Presenter = presenter; _findReferencesWindow = findReferencesWindow; TableControl = (IWpfTableControl2)findReferencesWindow.TableControl; // If the window is closed, cancel any work we're doing. _findReferencesWindow.Closed += OnFindReferencesWindowClosed; Debug.Assert(_findReferencesWindow.Manager.Sources.Count == 0); // And add ourselves as the source of results for the window. // Additionally, add custom columns to display custom reference information. _findReferencesWindow.Manager.AddSource(this, customColumns.Select(c => c.Name).ToArray()); // After adding us as the source, the manager should immediately call into us to // tell us what the data sink is. Debug.Assert(_tableDataSink != null); // Initialize custom column states at start of the FAR query. _customColumnTitleToStatesMap = GetInitialCustomColumnStates(findReferencesWindow.TableControl.ColumnStates, customColumns); // Now update the custom columns' state/visibility in the FAR window. // Note that the visibility of the custom column(s) can change only at two possible places: // 1. FAR query start, i.e. below invocation to SetColumnStates and/or // 2. First reference result which has a non-default custom column value // (UpdateCustomColumnVisibility method below). // Also note that the TableControl.SetColumnStates is not dependent on order of the input column states. TableControl.SetColumnStates(_customColumnTitleToStatesMap.Values); }
private void UpdateCustomColumnsVisibility(ImmutableDictionary <string, ImmutableArray <string> > additionalPropertiesWithMultipleValues) { // Check if we have any custom reference data to display. // columnDefinitionManager will be null under unit test var columnDefinitionManager = TableControl.ColumnDefinitionManager; if (additionalPropertiesWithMultipleValues.Count == 0 || columnDefinitionManager == null) { return; } // Get the new column states corresponding to the custom columns to display for custom data. var newColumnStates = ArrayBuilder <ColumnState2> .GetInstance(); try { lock (Gate) { foreach (var customColumnName in additionalPropertiesWithMultipleValues.Keys) { // Get the matching custom column. var customColumnDefinition = columnDefinitionManager.GetColumnDefinition(customColumnName) as AbstractCustomColumnDefinition; if (customColumnDefinition == null) { Debug.Fail($"{nameof(SourceReferenceItem.AdditionalPropertiesWithMultipleValues)} has a key '{customColumnName}', but there is no exported '{nameof(AbstractCustomColumnDefinition)}' with this name."); continue; } // Ensure that we flip the visibility to true for the custom column. // Note that the actual UI update happens outside the lock when we // invoke "TableControl.SetColumnStates" below. ColumnState2 newColumnStateOpt = null; if (_customColumnTitleToStatesMap.TryGetValue(customColumnDefinition.Name, out var columnState)) { if (!columnState.IsVisible) { newColumnStateOpt = new ColumnState2(columnState.Name, isVisible: true, columnState.Width, columnState.SortPriority, columnState.DescendingSort, columnState.GroupingPriority); } } else { newColumnStateOpt = customColumnDefinition.DefaultColumnState; } if (newColumnStateOpt != null) { _customColumnTitleToStatesMap[customColumnDefinition.Name] = newColumnStateOpt; newColumnStates.Add(newColumnStateOpt); } } } // Update the column states if required. if (newColumnStates.Count > 0) { // SetColumnStates API forces a switch to UI thread, so it should be safe to call // from a background thread here. // Also note that we will call it only once for each new custom column to add for // each find references query - the lock above guarantees that newColumnStatesOpt is // going to be non-null only for the first result that has a non-empty column value. TableControl.SetColumnStates(newColumnStates.ToImmutable()); } } finally { newColumnStates.Free(); } }