I'm trying to add inlines to a text block using the code below. The text block's window uses a Themes.xaml file for styling, but when I add the runs dynamically, the styling does not get applied. Can you help me understand why?
foreach (string key in wrappingOptions.Keys)
{
Hyperlink link = new Hyperlink(new Run(key));
string s = new string(wrappingOptions[key].ToCharArray());
link.Click += (o, _) => tbIn.SelectedText = string.Format("<{0}>{1}</{0}>",
s, tbIn.SelectedText);
InputLinksBlock.Inlines.Add(link);
}
Hyperlink is a FrameworkContentElement class. It does not derive it's text display properties from the parent TextBlock. You explicitly need to set a default style for a Hyperlink using <Style TargetType="Hyperlink">.
Related
First of all I am from Iran and I can't speak English very well, sorry for this.
I made something like OpenFileDialog in WinForms and it works correctly.
After that for better User Interface I'm try to make it in WPF.
I use TreeView and other controls to make it work in both platforms (Winforms and WPF).
In WPF I want to get the text of Treeview item for comparison, in Winform I could do this with below code:
private void Folder_FileTreeView_NodeMouseDoubleClick(object sender, TreeNodeMouseClickEventArgs e)
{
if(e.Node.Text=="Desktop")
{
//Do something
}
}
in WPF I added text with and image next to each other using this method:
public object Node(string NodeIMGUri, string NodeText)
{
Image IMG = new Image() { Source = new System.Windows.Media.Imaging.BitmapImage(new Uri(NodeIMGUri, UriKind.RelativeOrAbsolute)) };
TextBlock Text = new TextBlock() { Text = NodeText };
StackPanel CustomStackPanel = new StackPanel();
TreeViewItem TVItem = new TreeViewItem();
IMG.Height = 50;
IMG.Width = 50;
CustomStackPanel.Orientation = Orientation.Horizontal;
CustomStackPanel.Children.Add(IMG);
CustomStackPanel.Children.Add(Text);
TVItem.Header = CustomStackPanel;
return TVItem;
}
But when in SelectedItemChanged (or ItemChanged) event of TreeView how can I get the text of the item clicked?
If anyone can help me to complete this dll, I can send it free to all programmers.
This dll supports most languages like german, france, china, hindi, bengali, indonesian, persian, japanese, korean, arabic, portuguese, latin, swede, english
The way you are currently doing things, you would need to go through the children of your item to find the TextBlock and get the Text property from that. But this isn't the proper or recommended way of doing things in WPF.
Instead of manually creating TreeViewItems, you shoudl be using TreeView.ItemsSource and TreeView.ItemTemplate. If you're not familiar with how to use DataTemplates in WPF, you should really read up on it. Here is a good place to start.
Basically you would define a class, let's say Folder, then you would have a collection of Folder objects (e.g. List<Folder>), and you would bind that to TreeView.ItemsSource. You would then use a DataTempalte to declare the visual representation of how a Folder object should look in the TreeView. Then, when the selected item is changed, you can use TreeViewItem.DataContext to get the Folder object that is being selected, which would probably have a property such as Path.
So what I can see there you put into your TreeViewItem's header a panel with two items - Image and TextBlock with Text you want to get. The TextBlock is stored as the second item in the panel's collection (Children). All you have to do is this:
private void TreeView_SelectedItemChanged(object sender, RoutedPropertyChangedEventArgs<object> e)
{
CustomStackPanel panel = (CustomStackPanel)((TreeViewItem) e.NewValue).Header;
TextBlock textBlock = (TextBlock)panel.Children[1];
string text = textBlock.Text; //Your text
}
Hope it helps.
Background:
I have created a helper method to set properties of each TextBlockas per its adjacent TextBox for some scenarios in my application. In this method I already have the TextBlock object, the TextBox object and the parent object (it's always RelativePanel in my case).
The RelativePanel in my views always contain only TextBox & TextBlock.
// Helper Method
public static void SetPropertiesOfEachTextBlock(IList<TextBox> boxes)
{
foreach (TextBox textBox in boxes)
{
var parent = VisualTreeHelper.GetParent(textBox) as RelativePanel;
foreach(var element in parent.Children)
{
if(element is TextBlock)
{
TextBlock textBlock = (TextBlock)element;
textBlock.FontSize = textBox.FontSize;
textBlock.Margin = textBox.Margin;
textBlock.FontWeight = textBox.FontWeight;
textBlock.Foreground = new SolidColorBrush(Colors.Gray);
// Here I need to set alignment to the adjacent TextBox by the RelativePanel
}
}
}
}
Relative Panel Sample:
<RelativePanel>
<TextBox Name="UserName"/>
<TextBlock RelativePanel.AlignLeftWith="UserName" />
</RelativePanel>
Question:
How can I set the following property of TextBlock programmatically:
RelativePanel.AlignLeftWith="UserName"
AlignLeft is an Attached Property and can be found on RelativePanel itself. You set them like this:
RelativePanel.SetAlignLeftWith(element, UserName);
You can read the docs on the property here:
Edit: fixed syntax error based on comment
I am parsing HTML, generating a various blocks and adding them to RichTextBlock control. However, when I generate a Hyperlink from code behind I don't know how to remove underline property. I've seen posts about creating a HyperlinkButton and setting its Content property but it is definitely not something that I want because I can't make it to be in line with the rest of the text and it looks awful.
Below is the relevant code for generating a hyperlink:
private static Inline GenerateHyperLink(HtmlNode node)
{
Span s = new Span();
InlineUIContainer iui = new InlineUIContainer();
Hyperlink link = new Hyperlink();
link.Inlines.Add(new Run() { Text = node.InnerText });
link.NavigateUri = new Uri(node.Attributes["href"].Value, UriKind.Absolute);
s.Inlines.Add(link);
s.Inlines.Add(new Run() { Text = " " });
return s;
}
From MSDN:
A Hyperlink has a class inheritance that doesn't include
FrameworkElement, so it doesn't have a Style property. Nor does a
Hyperlink have a Template (it's not a true control).
Does it mean that there is no way to achieve that using Hyperlink element?
As per MSDN (emphasis mine):
If the Temporary property is true, the ContentControl is automatically deleted when the user types in the control, or when the text in the control is changed programmatically. When the ContentControl is automatically deleted from the document, the text in the control remains in the document.
It's working for "when the user types in the control" using Word Editor, but not when I change Text in (C#) code. My code is as below.
Make a tag Temporary
static void MakeTagsTemporary(List<Tag> tagList)
{
tagList.ForEach(x => x.Parent.Append(new TemporarySdt() { Val = true }));
} mainPart.Document.Save();
I am saving specifically to accept changes of making the Content Control Temporary, but with no effect.
Edit the text
static void ApplyProductGrid(MainDocumentPart mainPart, Plan pl, List<Tag> tagList)
{
foreach (Tag tagitem in tagList)
{
string GridValue = pl.FormattedTags.Where(x => x.Key == tagitem.Val).Select(x => x.Value).FirstOrDefault();
tagitem.Parent.Parent.Descendants<Text>().FirstOrDefault().Text = GridValue;
}
}
The line tagitem.Parent.Parent.Descendants<Text>().FirstOrDefault().Text = GridValue; is doing its job, its updating the value but Content Control is not removed.
When I edit something from word, Content Control is getting deleted.
I am adding tabs to my tab control through code:
TabItem tab = new TabItem();
var stack = new StackPanel() { Orientation = Orientation.Horizontal };
stack.Children.Add(new TextBlock() { Text = header });
stack.Children.Add(new TextBlock() { Name = "extra" });
tab.Header = stack;
tabControl.Items.Add(tab);
As you can see, it creates the header of the tabItem with a stack panel. It adds two text blocks; one of which is empty, but I've assigned the name "extra". What I would like to do is, later in the code, edit the textBlock named "extra" and add some new text to it.
How would I find and edit this element? I have tried the following code, but its producing an error saying the element can not be found:
object test = Application.Current.FindResource("extra");
FindName is what you are looking for but your TextBlock is not in the correct WPF Namescope.
MSDN states:
If you add an object to an object tree at a point in time after the XAML that produced that tree was parsed, a Name or x:Name value on the new object does not automatically update the information in a XAML namescope. To add a name for an object into a WPF XAML namescope after XAML is loaded, must call the appropriate implementation of RegisterName on the object that defines the XAML namescope.
For example:
var textBlock = new TextBlock() { Name = "extra" };
stack.Children.Add(textBlock );
RegisterName(textBlock);
...
TextBlock textBlock = FindName("extra") as TextBlock;
Finally, Application.Current.FindResource("extra") is returning null because the element does not exist when project resources are created. More on FindResource.
Just use FrameworkElement.FindName method:
var control = tab.FindName("extra");
if(control is TextBlock){
// your logic here
}
You don't need Application.Current.Resource dictionary here because it's different collection. If you want to use it then you should put user controls within Resource dictionary beforehand.
Because you are trying to find resource with the key "extra". It's wrong.
Try this:
TabItem tab = new TabItem();
var stack = new StackPanel() { Orientation = Orientation.Horizontal };
var textBlock = new TextBlock() { Name = "extra" }
stack.Children.Add(new TextBlock() { Text = header });
stack.Children.Add(textBlock);
tab.Header = stack;
tabControl.Items.Add(tab);
Now you can reach it with textBlock instance.
Here's some VB WPF code for what you need
Dim test As TextBlock
test = DirectCast(FindName("extra"), TextBlock)
I have no idea if it will work like that in C# WPF although if that doesn't work try looking up CType