Create textblock with textrun object at runtime - c#

iam trying to create a TextBlock with runobject at runtime.
i need the textblock to show following text:
Please Click Here to go to next Page.
Click here should be a "link" like, where the user can click on it and he will move to the next tabitem ..
i have:
var tbGoToNextTab = new TextBlock
{
Content = "Please Click Here to go to next Page.",
Foreground = new SolidColorBrush(Colors.Black)
};
tbGoToNextTab .Click +=new RoutedEventHandler(tbGoToNextTab_Click);
how would i just make the Click Here Clickable, have underline and blue text color and perform an action when clicking on it ?
thanks in advance
EDIT:
I just want the 2 Words "Click Here" clickable ...the rest should be displayed as normal text..
I think i should be doing this with Inlines.. any suggestions ?

Something like this? (untested)
var hyperlink = new HyperLink(new Run("Click Here"));
hyperlink.Click += new RoutedEventHandler(tbGoToNextTab_Click);
var span = new Span();
span.Inlines.Add(new Run("Please "));
span.Inlines.Add(hyperlink);
span.Inlines.Add(new Run(" to go to next Page"));
var tbGoToNextTab = new TextBlock
{
Content = span,
Foreground = new SolidColorBrush(Colors.Black)
};

Ok found the Answer ...
As i supposed i had to use the Inline property ..
i found the answer in this post:
Add hyperlink to textblock wpf From Stanislav Kniazev
Thanks all...

To manage a left click action, add a handler on the PreviewMouseLeftButtonDown
tbGoToNextTab.PreviewMouseLeftButtonDown += OntbGoToNextTabPreviewMouseLeftButtonDown;
void OntbGoToNextTabPreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
// write code here...
}
To manage underline and color change, write a Style in xaml, in this Style put a Trigger that will change your TextBlock on the IsMouseOver property change.
<Window.Resources>
<Style x:Key="HyperLinkStyle" TargetType="{x:Type TextBlock}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="TextDecorations" Value="Underline" />
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
tbGoToNextTab.Style = FindResource("HyperLinkStyle") as Style;
You will have to declare a TextBlock specifically for the clickable text and other TextBlocks for the static text.

Have something like this..
Textblock as content in the button..so that its clickable.
Canvas pnel = new Canvas();
var btntab = new Button();
var tbGoToNextTab1 = new TextBlock();
var tbGoToNextTab2 = new TextBlock();
var tbGoToNextTab3 = new TextBlock();
tbGoToNextTab1.Text = "Please ";
tbGoToNextTab2.Text = "Click Here";
tbGoToNextTab3.Text = " to go to next Page.";
tbGoToNextTab1.Margin = new Thickness(0, 0, 0, 0);
btntab.Margin = new Thickness(40, 0, 0, 0);
tbGoToNextTab3.Margin = new Thickness(95, 0, 0, 0);
tbGoToNextTab1.Foreground = new SolidColorBrush(Colors.Black);
tbGoToNextTab2.Foreground = new SolidColorBrush(Colors.Black);
tbGoToNextTab3.Foreground = new SolidColorBrush(Colors.Black);
btntab.Click += new RoutedEventHandler(btntab_Click);
btntab.Content = tbGoToNextTab2;
pnel.Children.Add(tbGoToNextTab1);
pnel.Children.Add(btntab);
pnel.Children.Add(tbGoToNextTab3);
Text112.Children.Add(pnel);

If you handle Click event for the TextBlock, it will process click anywhere within the boundary of the control.
If you need only part of the text clickable, you should place a Hyperlink within the body of your TextBlock. By the way, it has an extra benefit of highlighting the clickable area so that your was not confused with the text that says, "Click Here" which is not clickable.
Here's relevant WPF snippet:
<TextBlock>
<Run>Please</Run>
<Hyperlink>
<Run Text="Click Here"/>
</Hyperlink>
<Run>to go to next Page.</Run>
</TextBlock>

Related

Alerting User By Changing Background of Control C#

I'm programming in WPF(C#). I want to alert users about filling empty text box (or any other controls). I want to flash control to alert him/her. This is the codes that I used them but it does not change color:
static void AlertByChangingBackground(Control control)
{
Action a = () =>
{
control.Background = System.Windows.Media.Brushes.Red;
Thread.Sleep(500);
control.Background = System.Windows.Media.Brushes.White;
};
control.Dispatcher.Invoke(a);
}
As it can be seen, I also use Action but it does not work. I also use control.UpdateLayout() before Sleep method but it does not working, too. How can I fix the problem.
Update 1:
Now, I use codes illustrated below. But the problem is when the function is called several times (specially when it is called continuously in short times) the color of text does not back to its first color. For example my control may be remain at red color. How can I fix it?
public static void AlertByChangingBackground(Control control)
{
Action a = () =>
{
ColorAnimation animation;
animation = new ColorAnimation();
animation.From = Colors.Red;
animation.To = ToColor(control.Background);
animation.Duration = new Duration(new TimeSpan(0, 0, 0, 0, 330));
RepeatBehavior rb = new RepeatBehavior(3);
animation.RepeatBehavior = rb;
control.Background = new SolidColorBrush(Colors.Red);
control.Background.BeginAnimation(SolidColorBrush.ColorProperty, animation);
};
control.Dispatcher.BeginInvoke(a);
}
I note that I want to start animation from current background of my control, not from white or any predefined color.
You can use triggers or animations to alert the user rather than using thread,
you can add xmlns:sys="clr-namespace:System;assembly=mscorlib" namespace for checking the string is empty or not.
<Style TargetType="{x:Type TextBox}" x:Key="AlertStyle">
<Style.Triggers>
<DataTrigger Binding="{Binding Text,RelativeSource={RelativeSource Mode=Self}}" Value="{x:Static sys:String.Empty}">
<Setter Property="Background" Value="Red"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
use this style for your TextBox control like follows,
<TextBox Width="100" Height="25" Style="{StaticResource AlertStyle}">

C# working with button when button name is in a list

I have a few button created from a list, I now need to change one of the buttons image.
i am now trying to convert the string to a button.
How do i take the string and turn it in to a button that i can then work with ?
i have tried this:
Button button = (Button)this.FindName("button_" + list[0].ToString());
button.background = brush;
i get an error of Object reference not set to an instance of an object when i call button.background.
EDIT
this is how i have chosen to change the image of my button:
Uri resourceUri = new Uri("led_On.png", UriKind.Relative);
StreamResourceInfo streamInfo = Application.GetResourceStream(resourceUri);
BitmapFrame temp = BitmapFrame.Create(streamInfo.Stream);
var brush = new ImageBrush();
brush.ImageSource = temp;
Button button = (Button)FindName("button_" + list[0].ToString());
button.Background = brush;
i just cant grab the button with the name button_list[0].
One possible solution to change the WPF Button Image on Click event (C#) is listed below:
Listing 1. Changing Button Image on click (XAML)
<Button Name ="button1" Click="button1_Click">
<Button.Template>
<ControlTemplate TargetType="Button">
<Image x:Name="image1">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="Images/ContentImage.png" />
</Style>
</Image.Style>
</Image>
</ControlTemplate>
</Button.Template>
</Button>
Listing 2. C# code behind (button1.click event handler)
private void button1_Click(object sender, RoutedEventArgs a)
{
Image _img= button1.Template.FindName("image1", button1) as Image;
Style _imgStyle = new Style { TargetType = typeof(Image) };
_imgStyle.Setters.Add(new Setter(Image.SourceProperty, new BitmapImage(new Uri(#"pack://application:,,,/YourAssemblyName;component//Images/ContentImage1.png"))));
_img.Style = _imgStyle;
}
Pertinent to your code, it could be re-written in a simple form:
StreamResourceInfo _streamInfo =
Application.GetResourceStream(new Uri("led_On.png", UriKind.Relative));
button.Background = (new ImageBrush(){ImageSource=BitmapFrame.Create(_streamInfo.Stream)});
Just make sure that button object is not null (check this statement: "button_" + list[0] - may be just list[0]?)
Hope this may help.

Remove the default style of selected row

I know that question was ask a lot, but i only saw it in XAML code file.
I am working on a datagrid extension, so I am in C# code file and I would like to know how to remove the default style for selected row (In my case i want nothing change in the style, I have an image in row header that show wich row is selected).
Side question, can we have a selection like "Ctrl" is pressed and how in C# code?
Thanks
Edit
I try this code :
Style oRow = new Style(typeof(DataGridRow));
DataTrigger oTrigger2 = new DataTrigger();
Binding oBind = new Binding();
oBind.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(DataGridRow), 1);
oBind.Path = new PropertyPath(DataGridRow.IsSelectedProperty);
oTrigger2.Binding = oBind;
oTrigger2.Value = true;
oTrigger2.Setters.Add(new Setter(DataGridRow.BackgroundProperty, Brushes.Khaki));
oRow.Triggers.Add(oTrigger2);
this.RowStyle = oRow;
For now, i tryed to put the selected background in Khaki for test. But i get the old blue highlight.
Edit 2
Base on the idea of Sinatr, I change the DatagridRow for DatagridCell and ended with :
Style oRow = new Style(typeof(DataGridCell));
DataTrigger oTrigger2 = new DataTrigger();
Binding oBind = new Binding();
oBind.RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(DataGridRow), 1);
oBind.Path = new PropertyPath(DataGridRow.IsSelectedProperty);
oTrigger2.Binding = oBind;
oTrigger2.Value = true;
oTrigger2.Setters.Add(new Setter(DataGridCell.BackgroundProperty, null));
oTrigger2.Setters.Add(new Setter(DataGridCell.BorderBrushProperty, null));
oRow.Triggers.Add(oTrigger2);
this.RowStyle = oRow;
I only need to get the foreground of the row to set the foreground of the cell. But i got a new question with that solution, is ok to set background to null or i should bind it to thr row background?
You have to replace CellStyle control template.
To example, this stupid templating
<DataGrid x:Name="dataGrid">
<DataGrid.CellStyle>
<Style TargetType="DataGridCell">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DataGridCell">
<TextBlock Text="1" Background="Khaki" Foreground="Red"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGrid.CellStyle>
</DataGrid>
will produce this output (for just 1 Tuple<string, string, string>, whatever):
It stays the same for selected or not selected item.
Obviously you have to implement it more properly, but given answer should give you an idea.

WPF - duplicating a stackpanel

i have this (a rough e.g):
<StackPanel>
<StackPanel Orientation="Horizontal">
<Label .../>
<TextBox .../>
<Button Content="Add new input row" ... />
</StackPanel>
</StackPanel>
pretty self explanatory, i want to add a new Horizontal StackPanel with every click on the button..
is that possible?
thank you!
For this XAML above I will do like this:
In the click event handle of every button name "Add new input row", I mean you can use this event for all of buttons.
private void btn_Click(object sender, RoutedEventArgs e)
{
Button btn = sender as Button;
StackPanel stkButtonParent = btn.Parent as StackPanel;
StackPanel stkCover = stkButtonParent.Parent as StackPanel;
StackPanel newRow = NewRow();
stkCover.Children.Add(newRow);
}
private StackPanel NewRow() {
StackPanel stk = new StackPanel();
stk.Orientation = Orientation.Horizontal;
Label lbl = new Label();
lbl.Foreground = Brushes.Red; // some attribute
TextBox txt = new TextBox();
txt.Background = Brushes.Transparent; // some attribute
Button btn = new Button();
btn.Content = "Add new row";
btn.Click += btn_Click;
stk.Children.Add(lbl);
stk.Children.Add(txt);
stk.Children.Add(btn);
return stk;
}
Yes it is possible try handling the event like this for example:
// Create your StackPanel.
StackPanel sp = new StackPanel();
sp.Orientation = Orientation.Horizontal;
// Add controls to new StackPanel
// Control con = new Control();
// sp.Children.Add(con);
// Add created control to a previously created (and named) container.
myStackPanel.Children.Add(sp);
If you would like your StackPanel to contain some controls you can also add them to it here.
There is a way to do this via XamlReader as well, but I have never tried it.
Here is a link to a short article:
arcanecode.com

How to add a StackPanel in a Button in C# code behind

How to add a StackPanel in a Button using c# code behind (i.e. convert the following XAML to C# )? There is no Button.Children.Add...
<Button>
<StackPanel Orientation="Horizontal" Margin="10">
<Image Source="foo.png"/>
</StackPanel>
</Button>
Image img = new Image();
img.Source = new BitmapImage(new Uri("foo.png"));
StackPanel stackPnl = new StackPanel();
stackPnl.Orientation = Orientation.Horizontal;
stackPnl.Margin = new Thickness(10);
stackPnl.Children.Add(img);
Button btn = new Button();
btn.Content = stackPnl;
Set Button.Content instead of using Button.Children.Add
As a longer explanation:
Button is a control which "only has 1 child" - its Content.
Only very few controls (generally "Panels") can contain a list of zero or more Children - e.g. StackPanel, Grid, WrapPanel, Canvas, etc.
As your code already shows, you can set the Content of a Button to be a Panel - this would ehn allow you to then add multiple child controls. However, really in your example, then there is no need to have the StackPanel as well as the Image. It seems like your StackPanel is only adding Padding - and you could add the Padding to the Image rather than to the StackPanel if you wanted to.
Use like this
<Window.Resources>
<ImageSource x:Key="LeftMenuBackgroundImage">index.jpg</ImageSource>
<ImageBrush x:Key="LeftMenuBackgroundImageBrush"
ImageSource="{DynamicResource LeftMenuBackgroundImage}"/>
</Window.Resources>
and in Codebehind
Button btn = new Button();
btn.HorizontalContentAlignment = HorizontalAlignment.Stretch;
btn.VerticalContentAlignment = VerticalAlignment.Stretch;
StackPanel stk = new StackPanel();
stk.Orientation = Orientation.Horizontal;
stk.Margin = new Thickness(10, 10, 10, 10);
stk.SetResourceReference(StackPanel.BackgroundProperty, "LeftMenuBackgroundImageBrush");
btn.Content = stk;
In Xaml :
<Button x:Name="Btn" Click="Btn_Click" Orientation="Horizontal" Margin="10">
<StackPanel>
<Image Source="foo.png" Height="16" Width="16"/>
</StackPanel>
</Button>
In C# :
Button btn = new Button();
StackPanel panel = new StackPanel();
Image img = new Image
{
Source = "../foo.png"
}
panel.Children.Add(img);
btn.Content = panel;
I advise you to put the image in xaml resources :
<Window.Resources>
<BitmapImage x:Key="Img" UriSource="/Img/foo.png"/>
</Window.Resources>
And call it like this :
Image img = new Image
{
Source = (BitmapImage)FindResource("Img")
};

Categories