How can I determine coordinates of a Hyperlink in WPF - c#

I have WPF window with a FlowDocument with several hyperlinks in it:
<FlowDocumentScrollViewer>
<FlowDocument TextAlignment="Left" >
<Paragraph>Some text here
<Hyperlink Click="Hyperlink_Click">open form</Hyperlink>
</Paragraph>
</FlowDocument>
</FlowDocumentScrollViewer>
In the C# code I handle Click event to create and show a new WPF Window:
private void Hyperlink_Click(object sender, RoutedEventArgs e)
{
if (sender is Hyperlink)
{
var wnd = new SomeWindow();
//wnd.Left = ???
//wnd.Top = ???
wnd.Show();
}
}
I need this window to appear next to hyperlink's actual position. So I assume it requires assigning values to the window's Left and Top properties. But I have no idea how to obtain hyperlink position.

You can use ContentStart or ContentEnd to get a TextPointer for the start or end of the hyperlink and then call GetCharacterRect to get the bounding box relative to the FlowDocumentScrollViewer. If you get a reference to the FlowDocumentScrollViewer, you can use PointToScreen to convert it to screen coordinates.
private void Hyperlink_Click(object sender, RoutedEventArgs e)
{
var hyperlink = sender as Hyperlink;
if (hyperlink != null)
{
var rect = hyperlink.ContentStart.GetCharacterRect(
LogicalDirection.Forward);
var viewer = FindAncestor(hyperlink);
if (viewer != null)
{
var screenLocation = viewer.PointToScreen(rect.Location);
var wnd = new Window();
wnd.WindowStartupLocation = WindowStartupLocation.Manual;
wnd.Top = screenLocation.Y;
wnd.Left = screenLocation.X;
wnd.Show();
}
}
}
private static FrameworkElement FindAncestor(object element)
{
while(element is FrameworkContentElement)
{
element = ((FrameworkContentElement)element).Parent;
}
return element as FrameworkElement;
}

Related

Word VSTO add-in: Change task pane width on position changed

I have a UserControl which by default is anchored at the bottom like this:
var customTaskPaneContent = new CustomTaskPaneContent(jobId, _ipcClient, document, AddCustomTaskPane);
var customTaskPane = CustomTaskPanes.Add(customTaskPaneContent, CustomTaskPaneTitle, document.ActiveWindow);
customTaskPane.DockPosition = Office.MsoCTPDockPosition.msoCTPDockPositionBottom;
customTaskPane.Height = 130;
customTaskPane.Visible = true;
customTaskPane.VisibleChanged += CustomTaskPane_VisibleChanged;
customTaskPane.DockPositionChanged += CustomTaskPane_DockPositionChanged;
private void CustomTaskPane_DockPositionChanged(object sender, EventArgs e)
{
var customTaskPane = sender as Microsoft.Office.Tools.CustomTaskPane;
if(customTaskPane != null)
{
if (customTaskPane.DockPosition == Office.MsoCTPDockPosition.msoCTPDockPositionFloating)
{
//ATTEMPT 1
//customTaskPane.Width = 1000;
//ATTEMPT 2
var userControl = customTaskPane.Control;
var size = new System.Drawing.Size(1500, 400);
userControl.Size = size;
}
}
}
When I drag the panel and its position changes to msoCTPDockPositionFloating the assigned dimensions are too small and I would like to change its width.
I have made several attempts but the dimensions are never changed. Which is the correct way to change the Width size?
Try to change the Size property of the content as well in the following way:
private void myCustomTaskPane_DockPositionChanged(object sender, EventArgs e)
{
Microsoft.Office.Tools.CustomTaskPane taskPane =
sender as Microsoft.Office.Tools.CustomTaskPane;
if (taskPane != null)
{
// Adjust sizes of user control and flow panel to fit current task pane size.
MyUserControl userControl = taskPane.Control as MyUserControl;
System.Drawing.Size paneSize = new System.Drawing.Size(taskPane.Width, taskPane.Height);
userControl.Size = paneSize;
userControl.FlowPanel.Size = paneSize;
// Adjust flow direction of controls on the task pane.
if (taskPane.DockPosition ==
Office.MsoCTPDockPosition.msoCTPDockPositionTop ||
taskPane.DockPosition ==
Office.MsoCTPDockPosition.msoCTPDockPositionBottom)
{
userControl.FlowPanel.FlowDirection =
System.Windows.Forms.FlowDirection.LeftToRight;
}
else
{
userControl.FlowPanel.FlowDirection =
System.Windows.Forms.FlowDirection.TopDown;
}
}
}
This code example assumes that the task pane contains a UserControl named MyUserControl, and the UserControl contains a FlowLayoutPanel named FlowPanel.
See CustomTaskPane Interface for the full sample code.

UWP Tab View not responding

I have a page with a Tab View. Inside every tab is another page. Whenever I try to interact with the tab, nothing works. I tried interacting with it with SettingsPage as the content, and it worked.
MainPage - contains the tabs
TabbedMainPage - contains the workspace
SettigsPage - contains settings
MainPage:
private void TabView_AddTabButtonClick(TabView sender, object args)
{
sender.TabItems.Add(CreateNewTab());
}
public TabViewItem OpenSettingsTab()
{
TabViewItem newItem = new TabViewItem();
newItem.Header = "Settings";
newItem.IconSource = new Microsoft.UI.Xaml.Controls.SymbolIconSource() { Symbol = Symbol.Setting };
Frame frame = new Frame();
frame.Navigate(typeof(SettingsPage));
newItem.Content = frame;
TabbedView.UpdateLayout();
return newItem;
}
public void CreateSettingsTab()
{
TabbedView.TabItems.Add(OpenSettingsTab());
TabbedView.UpdateLayout();
TabbedView.SelectedIndex = TabbedView.TabItems.Count - 1;
}
public TabViewItem CreateNewTab()
{
TabViewItem newItem = new TabViewItem();
newItem.Header = "New Tab";
newItem.IconSource = new Microsoft.UI.Xaml.Controls.SymbolIconSource() { Symbol = Symbol.Document };
Frame frame = new Frame();
frame.Navigate(typeof(TabbedMainPage));
newItem.Content = frame;
TabbedView.UpdateLayout();
return newItem;
}
private void TabbedView_Loaded(object sender, RoutedEventArgs e)
{
var S = sender as TabView;
if (S.TabItems.Count == 0)
{
S.TabItems.Add(CreateNewTab());
}
TabbedView.UpdateLayout();
}
TabbedMainPage has the following components: ColorPicker, DropDownButton, MenuBar, Border, Button, CheckBox, ComboBox, Flyout, Grid, Image, MenuFlyout, Pivot, PivotItem, StackPanel, TextBlock, TextBox, Flyout, Popup, RichEditBox, ScrollViewer, Slider, ToggleButton and Tooltip.
I think it might be caused by overloading with components, but I'm not sure. I also have these in my code:
MediaElement ME;
SpeechSynthesizer Synth;
public StorageFile TXTFile;
public IRandomAccessStream RAS;
private readonly PrintHelperOptions PP = new PrintHelperOptions();
var LS = ApplicationData.Current.LocalSettings;
var TB = ApplicationView.GetForCurrentView().TitleBar;
var CTB = CoreApplication.GetCurrentView().TitleBar;
I managed to fix the bug by removing the Pivot from the toolbar. It was interfering with the tab functionality, so I merged all the items together.

How to align the context menu to bottom right?

I have the below code which I use to open the context menu of a Rectangle:
private void RectBtn_MouseDown(object sender, MouseButtonEventArgs e)
{
var cm = ContextMenuService.GetContextMenu(sender as DependencyObject);
if (cm == null)
return;
else
{
cm.Placement = PlacementMode.Top;
cm.PlacementTarget = sender as UIElement;
cm.IsOpen = true;
}
}
So, my context menu, when appeared, looks as follows:
Is there a way to achieve the below look from code behind (keeping the above code)?
I looked at the solution on this SO post, but I need to achieve it from code behind. Any help would be appreciated.
Your code doesn't correspond to the images you posted. You set the Bottom placement, but on the screenshots, the context menu is positioned at the top of the target.
Anyway, you can use the Custom placement and calculate the position manually:
else
{
cm.Placement = PlacementMode.Custom;
cm.PlacementTarget = sender as UIElement;
cm.CustomPopupPlacementCallback =
(popupSize, targetSize, offset) =>
new[]
{
new CustomPopupPlacement
{
Point = new Point(targetSize.Width - popupSize.Width, targetSize.Height)
}
};
cm.IsOpen = true;
}

How do I force showing a tooltip in WPF

I'd like to show a tooltip when I move the mouse.
Here is my code:
private void Grid_MouseMove(object sender, MouseEventArgs e)
{
Grid grid = (Grid) sender;
if (e.GetPosition(grid).X < 100)
grid.ToolTip = e.GetPosition(grid).X.ToString();
else
grid.ToolTip = null;
}
However, the tooltip disappears after I click on the grid.
Is there a way to force showing the tooltip?
var oldTT = SomeElement.ToolTip as ToolTip;
if (oldTT != null) oldTT.IsOpen = false;
SomeElement.ToolTip = new ToolTip
{
Content = "Lalalalala",
IsOpen = true,
};
or
var tt = SomeElement.ToolTip as ToolTip;
if (tt != null) tt.IsOpen = true;
TooltipService.ShowDuration works, but you must set it on the object having the Tooltip, like this:
<Label ToolTipService.ShowDuration="120000" Name="lblTooltip" Content="Shows tooltip">
<Label.ToolTip>
<ToolTip>
<TextBlock>Hi world!</TextBlock>
</ToolTip>
</Label.ToolTip>

Hot to get cursor position relative to upper left corner of the control?

When I clicked on a control,
How to get cursor position relative to upper left corner of a (winforms) control ?
C#, VS 2005
PS:
I'm asking on context of tooltip "show" method which need that coordinates ..
This is my code to set tooltips on a composite control, might give you a clue (LED derivers from UserControl):
public LED()
{
InitializeComponent();
m_Image = global::AdvAdmittance.Controls.Properties.Resources.ledgray_small;
m_ToolTip = new ToolTip();
m_ToolTip.AutoPopDelay = 5000;
m_ToolTip.InitialDelay = 1000;
m_ToolTip.ReshowDelay = 500;
m_ToolTip.ShowAlways = true;
m_LedPictureBox.MouseHover += new EventHandler(m_LedPictureBox_MouseHover);
m_LedPictureBox.MouseLeave += new EventHandler(m_LedPictureBox_MouseLeave);
m_LedPictureBox.Click += new EventHandler(m_LedPictureBox_Click);
}
void m_LedPictureBox_MouseHover(object sender, EventArgs e)
{
if (m_ToolTipText != string.Empty)
{
Point toolTipPoint = this.Parent.PointToClient(Cursor.Position);
toolTipPoint.Y -= 20;
m_ToolTip.Show(m_ToolTipText, this.Parent, toolTipPoint);
}
}
void m_LedPictureBox_MouseLeave(object sender, EventArgs e)
{
m_ToolTip.Hide(this.m_LedPictureBox);
}
Ahh, Thanks for an answer.
All I need is a PointToClient method.
I hope (maybe) it will be useful for other people, here "my" code.
I took almost all code from http://support.microsoft.com/kb/322634 and modified three lines:
void treeView1_MouseMove(object sender, MouseEventArgs e)
{
// Get the node at the current mouse pointer location.
TreeNode theNode = this.treeView1.GetNodeAt(e.X, e.Y);
// Set a ToolTip only if the mouse pointer is actually paused on a node.
if ((theNode != null))
{
// Verify that the tag property is not "null".
if (theNode.Tag != null)
{
// Change the ToolTip only if the pointer moved to a new node.
if (theNode.Tag.ToString() != this.toolTip1.GetToolTip(this.treeView1))
{
//this.toolTip1.SetToolTip(this.treeView1, theNode.Tag.ToString());
Point c = System.Windows.Forms.Cursor.Position;
Point p = treeView1.PointToClient(c);
this.toolTip1.Show(theNode.Tag.ToString(), treeView1, p);
}
}
else
{
this.toolTip1.SetToolTip(this.treeView1, "");
}
}
else // Pointer is not over a node so clear the ToolTip.
{
this.toolTip1.SetToolTip(this.treeView1, "");
}
}
Have a look at
Windows Forms Coordinates
Control.PointToClient Method
C# Get a control’s position on a
form
Control PointToClient() vs
PointToScreen()

Categories