Hyperlink click action and ability to select and copy text - c#

I'm working on a WPF application in C# and need the ability for users to click a hyperlink(execute the command) but also have the ability to select the text and copy it.
I searched for options but could not find anything that would help me.
Currently i have the following in my WPF XAML:
<TextBlock Grid.Column="1" Grid.Row="0">
<Hyperlink Command="{Binding OpenDefaultMailApplicationCommand}" >
<TextBox Height="20" IsReadOnly="True" Foreground="Blue" BorderThickness="0">test#test.nl</TextBox>
</Hyperlink>
</TextBlock>
What am i doing wrong? The text is selectable only i don't have the ability to click on it to execute my command.

This is what I use for similar req.
You need to have a textbox, which is non editable and is clickable. you can style it as a hyperlink by making in underlined and color changes etc.
<TextBox IsReadOnly="True"
Background="Transparent"
BorderThickness="0"
Text="test#test.nl"
Height="20"
PreviewMouseLeftButtonDown="TextBox_PreviewMouseLeftButtonDown"
TextDecorations="Underline"
MouseMove="TextBox_MouseMove"
Foreground="Blue" />
private void TextBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (Keyboard.IsKeyDown(Key.LeftCtrl))
{
MessageBox.Show("CLicked");
}
}
private void TextBox_MouseMove(object sender, MouseEventArgs e)
{
var txtBox = sender as TextBox;
if (Keyboard.IsKeyDown(Key.LeftCtrl))
{
txtBox.Cursor = Cursors.Hand;
}
else
txtBox .Cursor = null;
}

So i found a other approach for the problem.
By using a richtextbox and adding a hyperlink to that, a user is able to select the text but can also click it.
<RichTextBox Name="rtbEmail" Grid.Column="1" Grid.Row="0" Foreground="Blue" BorderThickness="0"
Margin="3"/>
In the 'C#' usercontrol.cs i programmaticly set the hyperlink and add a click eventhandler to it.
FlowDocument doc = new FlowDocument();
rtbEmail.Document = doc;
rtbEmail.IsReadOnly = true;
rtbEmail.IsDocumentEnabled = true;
Paragraph para = new Paragraph();
doc.Blocks.Add(para);
Hyperlink link = new Hyperlink();
link.IsEnabled = true;
link.Inlines.Add(DataContext.EmailAddress);
link.Click += new RoutedEventHandler(this.OpenEmailAppEvent);
para.Inlines.Add(link);
Hopefully someone has use for this :). i did :)

Related

Using connected animation

<GridView x:Name="ForegroundElement" ItemsSource="{x:Bind Icons}" IsItemClickEnabled="True" ItemClick="Grid_Clicked">
<GridView.ItemTemplate>
<DataTemplate x:DataType="data:Icon">
<StackPanel>
<Image x:Name="ConnectedElement" Width="200" Height="200" HorizontalAlignment="Center" Source="{x:Bind ImageCover}"/>
<TextBlock FontSize="16" VerticalAlignment="Center" Text="{x:Bind Title}"/>
<TextBlock FontSize="10" VerticalAlignment="Center" Text="{x:Bind Room}"/>
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
this is my gridView contain the data
and this is my clicked event
private void Grid_Clicked(object sender, ItemClickEventArgs e)
{
var icon = (Icon)e.ClickedItem;
IconResult.Text = "You selected a " + icon.Title;
}
I wanna add the ConnectedAnimation when ever I click a "Stack" in the "GridView" to navigate the other page
Microsoft I have to create the "PrepareConnectedAnimation" method use this
but in my case I have a click event so what should I do to create and use this method ?
It is perfectly ok to put it inside the Clicked event. You first have to get hold of the item container itself. You can do that using the ContainerFromItem method of the GridView:
private void Grid_Clicked(object sender, ItemClickEventArgs e)
{
var icon = (Icon)e.ClickedItem;
IconResult.Text = "You selected a " + icon.Title;
var container = ForegroundElement.ContainerFromItem(e.ClickedItem) as GridViewItem;
if (container != null)
{
//find the image
var root = (FrameworkElement)container.ContentTemplateRoot;
var image = (UIElement)root.FindName("ConnectedElement");
//prepare the animation
ConnectedAnimationService.GetForCurrentView().PrepareToAnimate("Image", image);
}
Frame.Navigate(typeof(SecondPage));
}
Now on the second page you get hold of the animation and connect it:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
ConnectedAnimation imageAnimation =
ConnectedAnimationService.GetForCurrentView().GetAnimation("Image");
imageAnimation?.TryStart(TargetElement);
}
You can check out the exmple provided in the UWP Samples gallery on GitHub to see full implementation in action.

How to Pro-gramatically add click Event to FrameworkElementFactory

I'm trying to apply a data template programatically behind code. I've set the properties fine but I'm stuck on how to add the Click Event. May I ask how abouts do I do that?
Xaml Code that's being copied
<DataTemplate>
<telerik:RadToggleButton Content="+"
Width="20"
Height="20"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Click="RiskButton_OnClick"
Visibility="{Binding AttachmentVisibility, Mode=TwoWay, Converter={StaticResource BooleanToVisibilityConverter}}"/>
</DataTemplate>
What I currently have
var toggleButton = new FrameworkElementFactory(typeof(RadToggleButton));
toggleButton.SetValue(RadToggleButton.ContentProperty, "+");
toggleButton.SetValue(RadToggleButton.WidthProperty, 20.0);
toggleButton.SetValue(RadToggleButton.HeightProperty, 20.0);
toggleButton.SetValue(RadToggleButton.HorizontalContentAlignmentProperty, HorizontalAlignment.Center);
toggleButton.SetValue(RadToggleButton.VerticalAlignmentProperty, VerticalAlignment.Center);
//toggleButton.AddHandler(); <- what goes here?
DataTemplate dt = new DataTemplate
{
VisualTree = toggleButton
};
dt.Seal();
toggleButton.AddHandler(RadToggleButton.ClickEvent, new RoutedEventHandler(SomeHandler));
SomeHandler is a RoutedEventHandler:
public void SomeHandler(object sender, RoutedEventArgs e)
{
}

How to move text from one Textblock to another Textblock using Drag and Drop in a Universal Windows Application?

I know how to set properties like CanDrag and AllowDrop and define DragOver method and Drop method.
I just don't know what to write inside the Drop method.
How to move text from one Textblock to another Textblock using Drag and Drop
We can define DragStarting event for the source Textblock and save the text of the source Textblock in DragStartingEventArgs for transfer during dragging. And accept the text when drop at target Textblock. Read the text from DragEventHandler and set it to the target Textblock.
I wrote a simple sample here, move the text from txtsource to append to txttarget.
XAML code:
<StackPanel Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Padding="30">
<Border BorderBrush="Azure" BorderThickness="2">
<TextBlock x:Name="txtsource" Text="I'm the first textblock" CanDrag="True" DragStarting="txtsource_DragStarting" />
</Border>
<Border BorderBrush="Azure" BorderThickness="2" Margin="20" AllowDrop="True" >
<TextBlock x:Name="txttarget" Text="I'm the second textblock" Drop="txttarget_Drop" Height="50" Width="400" AllowDrop="True" DragEnter="txttarget_DragEnter"/>
</Border>
</StackPanel>
Code behind
private void txtsource_DragStarting(UIElement sender, DragStartingEventArgs args)
{
args.Data.SetText(txtsource.Text);
}
private async void txttarget_Drop(object sender, DragEventArgs e)
{
bool hasText = e.DataView.Contains(StandardDataFormats.Text);
e.AcceptedOperation = hasText ? DataPackageOperation.Copy : DataPackageOperation.None;
if (hasText)
{
var text = await e.DataView.GetTextAsync();
txttarget.Text +="\n"+ text;
}
}
private void txttarget_DragEnter(object sender, DragEventArgs e)
{
bool hasText = e.DataView.Contains(StandardDataFormats.Text);
e.AcceptedOperation = hasText ? DataPackageOperation.Copy : DataPackageOperation.None;
if (hasText)
{
e.DragUIOverride.Caption = "Drop here to insert text";
}
}
I use DragOver event to help define which area can be drop. More details please reference the scenario 2 of the official sample.

Dynamic tooltip with textblock in WPF

i'm have some trouble with tooltip in textblock wpf .
After i completed 1 task and if task is error i want update error info with tooltip . But tooltip never show when completed . Please help me .
Thanks
Here my code
C# code
if (status == "Error")
{
LogCreateSite item = (LogCreateSite)gridLog.Items[rowIndex];
item.ErrorInfo = "Error";
DataTemplate template = cellTitle.ContentTemplate;
Canvas canvas = (Canvas)template.LoadContent();
TextBlock txtError = (TextBlock)canvas.Children[1];
ToolTip toolTip = new ToolTip();
toolTip.Content = "asdfasdf";
txtError.ToolTip = toolTip;
txtError.UpdateLayout();
}
And my Xaml :
<DataTemplate x:Key="error">
<Canvas Margin="10,15,0,0">
<!--<Ellipse Fill="#FF5050" Width="12" Height="12">
</Ellipse>-->
<Viewbox Width="16" Height="16">
<Frame Source="../Icon/Error_16.xaml" />
</Viewbox>
<TextBlock Text="Error" Margin="25,-3,0,0">
</TextBlock>
<TextBlock Cursor="Hand" Name="txtErrorInfo" ToolTip="{Binding ErrorInfo, Mode=OneWay,UpdateSourceTrigger=PropertyChanged}" FontSize="14" Text="?" Margin="60,-3,0,0" FontWeight="Bold" Foreground="Blue">
</TextBlock>
</Canvas>
</DataTemplate>
You need to do binding for tool tip to show the error/message to user.
Please go thru this tutorial for wpf binding. Introduction to WPF data binding from WPF-tutorial.
your XAML should be like this for a proper binding.
Name="txtErrorInfo" ToolTip="{binding path=error mode=OneWay UpdateSourceTrigger=PropertyChanged}"
It is required to mention mode and UpdateSourceTrigger when you are changing the property which should be shown to user.
Correcting your code, see this sample for how to show ToolTip from code :
private void Button_Click_1(object sender, RoutedEventArgs e)
{
ToolTip t = new ToolTip();
t.Content = DateTime.Now.ToString();
t.IsOpen = true;
t.PlacementTarget = txtError;
t.Placement = System.Windows.Controls.Primitives.PlacementMode.Bottom;
txtError.ToolTip = t;
}

Finding a control inside another control in WPF

Since there is no link button in WPF I created a link button using hyperlink and text block controls.
There are 3 controls:
<TextBlock Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Left" >
<Hyperlink Name="hyplnkIsActiveMarkets" Click="hyplnkIsActive_Click" Foreground="Blue" >
<TextBlock Name="txtblkIsActiveMarkets" Text="Active" />
</Hyperlink>
</TextBlock>
<TextBlock Grid.Column="1" VerticalAlignment="Center" HorizontalAlignment="Left">
<Hyperlink Name="hyplnkIsActiveBudgets" Click="hyplnkIsActive_Click" Foreground="Blue" >
<TextBlock Name="txtblkIsActiveBudgets" Text="Active" />
</Hyperlink>
</TextBlock>
<TextBlock Grid.Column="2" VerticalAlignment="Center" HorizontalAlignment="Left">
<Hyperlink Name="hyplnkIsActivePrograms" Click="hyplnkIsActive_Click" Foreground="Blue" >
<TextBlock Name="txtblkIsActivePrograms" Text="Active" />
</Hyperlink>
</TextBlock>
All the link buttons calls same click method
private void hyplnkIsActive_Click(object sender, RoutedEventArgs e)
{
Hyperlink objHyperlink = (Hyperlink)sender;
TextBlock objTextBlock = new TextBlock();
if (objHyperlink == hyplnkIsActiveMarkets)
{
objTextBlock = txtblkIsActiveMarkets;
}
else if (objHyperlink == hyplnkIsActiveBudgets)
{
objTextBlock = txtblkIsActiveBudgets;
}
else if (objHyperlink == hyplnkIsActivePrograms)
{
objTextBlock = txtblkIsActivePrograms;
}
if (objTextBlock.Text == "Active")
ChangeHyperLinkStatus(objHyperlink, objTextBlock, Status.Inactive);
else ChangeHyperLinkStatus(objHyperlink, objTextBlock, Status.Active);
}
In the click method I check for the text block inside the hyper link individually using if condition.
Is there any easier way to do this? That's basically finding control inside a control?
UPDATE: you can not use VisualTreeHelper.GetParent(...) to get the parent of your hyperlink as you have mentioned hyperlink is not visual. corrected the answer.
See code below.
private void hyplnkIsActive_Click(object sender, RoutedEventArgs e)
{
Hyperlink objHyperlink = (Hyperlink)sender;
TextBlock objTextBlock = (TextBlock)LogicalTreeHelper.GetChildren(objHyperlink)[0];
// This will give logical tree first child of objHyperlink
if (objTextBlock.Text == "Active")
ChangeHyperLinkStatus(objHyperlink, objTextBlock, Status.Inactive);
else
ChangeHyperLinkStatus(objHyperlink, objTextBlock, Status.Active);
}
See this article about logical tree on MSDN
I think you're going into the wrong direction by relaying your execution logic on controls and not on data.
You can, for example, bind a ICommand or RelayCommand to the buttons, or just subscribe different events, or define a custom DataTemplate where on mouse down the clicked control is assignable to some ModelView property.
Doing in way you do, you create tough coupling between UI and your execution logic.
In this case easier use WindowsForm then WPF.
I got it finally . Thanks to Maheep fa his help
TextBlock objTextBlock = (TextBlock)LogicalTreeHelper.GetChildren(objHyperlink).Cast<System.Windows.Documents.InlineUIContainer>().FirstOrDefault().Child;

Categories