Get width of a Dockpane pro sdk

296
9
Jump to solution
07-17-2020 02:28 PM
MarvisKisakye1
Occasional Contributor

I have created help content for input parameters on a dockpane which shows up when the user hovers over the info icon to the left of the input parameter as a tooltip. I would like for the tooltip to show up not on the dockpane but to the right of the dockpane. I figured the best way to achieve this would be to set the HorizontalOffset of the tooltip to the width of the dockpane. To achieve this, I need to know the width of the user's dockpane. I figured it would be best to dynamically retrieve the width of the dockpane and use that as the HorizontalOffset  of the tooltip. So how do I access the width of a dockpane. I checked the 'pane' help but it has no width property. Uma HaranoWolfgang Kaiser

0 Kudos
1 Solution

Accepted Solutions
Wolf
by Esri Regular Contributor
Esri Regular Contributor

Try this - eventually you should change the PaneWidth datatype to double.  Note that the snippet below tracks any changes to the width by using the SizeChanged event, covering the case when the operator resizes the dockpane after its initial display.

private bool _initSizeChange = true;

private double GetWidth()
{
if (_initSizeChange) {
_initSizeChange = false;
base.Content.SizeChanged += Content_SizeChanged;
}
return base.Content.ActualWidth;
}

private void Content_SizeChanged(object sender, System.Windows.SizeChangedEventArgs e)
{
if (e.WidthChanged)
{
PaneWidth = GetWidth().ToString();
}
}

public string _paneWidth = string.Empty;
public string PaneWidth
{
get
{
if (string.IsNullOrEmpty (_paneWidth))
{
_paneWidth = GetWidth().ToString();
}
return _paneWidth;
}
set
{
SetProperty(ref _paneWidth, value, () => PaneWidth);
}
}

View solution in original post

0 Kudos
9 Replies
ThanHtetAung_EsriAu
Esri Regular Contributor

Hi Marvis Kisakye‌,

For right alignment with offset, I think using HorizontalAlignment = "Right" with margin property for offset will do the job for you.

<Grid  Margin="5,0" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="40"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid Grid.Row="0" Margin="5" HorizontalAlignment="Right" >
.......

FrameworkElement.Margin Property (System.Windows) | Microsoft Docs 

Alignment, Margins, and Padding Overview - WPF | Microsoft Docs 

Or you can create the margin property and shift the item based on the size of your control as well.

That could be easier I think.

0 Kudos
MarvisKisakye1
Occasional Contributor

Yes. My problem is that I need to know the width of the dockpane so that I can set the margin/horizontal offset value. This way, the tooltip always appears just to the right of the dockpane even if it gets resized by the user.

0 Kudos
JohnJones
Esri Contributor
0 Kudos
Wolf
by Esri Regular Contributor
Esri Regular Contributor

Hi Marvis,

 There is no easy way to do this right now, however, there is a workaround since the 'Content' property is 'protected internal' and hence accessible from any derived class (which includes your dockpane).  To test this i added a button to my test dockpane class (CmdWidthTest) that calls the added 'GetFrameworkElement' function.  Needless to say you can make this a property as well.  To access the width use the 'ActualWidthProperty'.

public System.Windows.FrameworkElement GetFrameworkElement()
{
return base.Content;
}

public ICommand CmdWidthTest
{
get
{
return new RelayCommand(() =>
{
var ui = GetFrameworkElement();
MessageBox.Show($@"Width: {ui.ActualWidth}");
});
}
}
0 Kudos
MarvisKisakye1
Occasional Contributor

Wolfgang Kaiser This works well as a button but how do I set it as a property? I attempted to set it as below:

public string _paneWidth = base.Content.ActualWidth.ToString();
public string PaneWidth
{
get { return _paneWidth; }
set
{
SetProperty(ref _paneWidth, value, () => PaneWidth);
}
}

But I get the error "keyword base is not available in the current context"

0 Kudos
Wolf
by Esri Regular Contributor
Esri Regular Contributor

Try this - eventually you should change the PaneWidth datatype to double.  Note that the snippet below tracks any changes to the width by using the SizeChanged event, covering the case when the operator resizes the dockpane after its initial display.

private bool _initSizeChange = true;

private double GetWidth()
{
if (_initSizeChange) {
_initSizeChange = false;
base.Content.SizeChanged += Content_SizeChanged;
}
return base.Content.ActualWidth;
}

private void Content_SizeChanged(object sender, System.Windows.SizeChangedEventArgs e)
{
if (e.WidthChanged)
{
PaneWidth = GetWidth().ToString();
}
}

public string _paneWidth = string.Empty;
public string PaneWidth
{
get
{
if (string.IsNullOrEmpty (_paneWidth))
{
_paneWidth = GetWidth().ToString();
}
return _paneWidth;
}
set
{
SetProperty(ref _paneWidth, value, () => PaneWidth);
}
}

View solution in original post

0 Kudos
MarvisKisakye1
Occasional Contributor

This works perfectly Wolf. Thank you.

0 Kudos
SteveVan_Esch
New Contributor III

Maybe something like this. I'm manually positioning the tooltip relative to the view's outermost grid.

<Grid x:Name="mainGrid">
<Button x:Name="myButton" Content="Test" Width="100" Height="40">
<Button.ToolTip>
<ToolTip x:Name="popup1" Placement="Custom">test</ToolTip>
</Button.ToolTip>
</Button>‍‍‍‍‍‍‍‍‍‍‍‍

    public Dockpane1View()
{
InitializeComponent();

popup1.CustomPopupPlacementCallback = new CustomPopupPlacementCallback(placePopup);
}

public CustomPopupPlacement[] placePopup(Size popupSize, Size targetSize, Point offset)
{
double scaleX = 1;

PresentationSource source = PresentationSource.FromVisual(mainGrid);

// Get the display scale (e.g. 200%)
if (source != null)
scaleX = source.CompositionTarget.TransformToDevice.M11;

Point newPoint = myButton.TranslatePoint(new Point(0, 0), mainGrid);

CustomPopupPlacement placement1 =
new CustomPopupPlacement(new Point(((mainGrid.ActualWidth - newPoint.X) * scaleX) + (5 * scaleX), 0), PopupPrimaryAxis.Vertical);

CustomPopupPlacement placement2 =
new CustomPopupPlacement(new Point((newPoint.X * scaleX * -1) - popupSize.Width - (5 * scaleX), 0), PopupPrimaryAxis.Horizontal);

CustomPopupPlacement[] placements = new CustomPopupPlacement[] { placement1, placement2 };
return placements;
}
}‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
0 Kudos
MarvisKisakye1
Occasional Contributor

Thanks for the response. I would rather use the MVVM pattern and avoid code behind.

0 Kudos