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 Harano Wolfgang Kaiser
Solved! Go to Solution.
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);
}
}
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.
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.
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}");
});
}
}
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"
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);
}
}
This works perfectly Wolf. Thank you.
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;
}
}
Thanks for the response. I would rather use the MVVM pattern and avoid code behind.