C# - Read Paragraph From Rich Text Box - c#

How do I read a paragraph from rich text box in WPF and display it in a Message Box?

If you want to iterate through all the paragraphs in a RichTextBox, then the following static classes containing extension methods provide the necessary methods:
public static class FlowDocumentExtensions
{
public static IEnumerable<Paragraph> Paragraphs(this FlowDocument doc)
{
return doc.Descendants().OfType<Paragraph>();
}
}
public static class DependencyObjectExtensions
{
public static IEnumerable<DependencyObject> Descendants(this DependencyObject root)
{
if (root == null)
yield break;
yield return root;
foreach (var child in LogicalTreeHelper.GetChildren(root).OfType<DependencyObject>())
foreach (var descendent in child.Descendants())
yield return descendent;
}
}
Once you have collected all the paragraphs in a FlowDocument, to convert a single paragraph to text, you can do:
var text = new TextRange(paragraph.ContentStart, paragraph.ContentEnd).Text;
And example of how to put these together is:
foreach (var paragraph in canvas.Document.Paragraphs())
{
MessageBox.Show(new TextRange(paragraph.ContentStart, paragraph.ContentEnd).Text);
}
Is that what you want?
Update
If for whatever reason you are uncomfortable using extension methods, you could always use traditional c# 2.0 static methods:
public static class FlowDocumentExtensions
{
public static IEnumerable<Paragraph> Paragraphs(FlowDocument doc)
{
return DependencyObjectExtensions.Descendants(doc).OfType<Paragraph>();
}
}
public static class DependencyObjectExtensions
{
public static IEnumerable<DependencyObject> Descendants(DependencyObject root)
{
if (root == null)
yield break;
yield return root;
foreach (var child in LogicalTreeHelper.GetChildren(root).OfType<DependencyObject>())
foreach (var descendent in child.Descendants())
yield return descendent;
}
}
And
foreach (var paragraph in FlowDocumentExtensions.Paragraphs(mainRTB.Document))
{
MessageBox.Show(new TextRange(paragraph.ContentStart, paragraph.ContentEnd).Text);
}

Related

Mapping binary search tree

I have this binary search tree with Node class and I need to write mapping and filtering method for it but I have no clue how can I go through the whole tree. My every attempt to go through it skipped almost half of the tree.
public class BST<T> where T:IComparable<T>
{
public class Node
{
public T value { get; }
public Node left;
public Node right;
public Node(T element)
{
this.value = element;
left = null;
right = null;
}
}
private Node root;
private void add(T element)
{
if (root == null)
root = new Node(element);
else
{
add(element, root);
}
}
public void add(T element, Node leaf)
{
if(element.CompareTo(leaf.value) > 0)
{
if (leaf.right == null)
leaf.right = new Node(element);
else
add(element,leaf.right);
}
else
{
if (leaf.left == null)
leaf.left = new Node(element);
else
add(element, leaf.left);
}
}
}
I have no clue how can I go through the whole tree
There are many ways to do that. One is to make your class iterable.
For that you can define the following method on your Node class:
public IEnumerator<T> GetEnumerator()
{
if (left != null) {
foreach (var node in left) {
yield return node;
}
}
yield return value;
if (right != null) {
foreach (var node in right) {
yield return node;
}
}
}
And delegate to it from a similar method on your BST class:
public IEnumerator<T> GetEnumerator()
{
if (root != null) {
foreach (var node in root) {
yield return node;
}
}
}
Now you can write code like this:
var tree = new BST<int>();
tree.add(4);
tree.add(2);
tree.add(3);
tree.add(6);
tree.add(5);
foreach (var value in tree) {
Console.WriteLine(value);
}
I need to write mapping and filtering method for it
It depends on what you want the result of a mapping/filtering function to be. If it is just a sequence of values, the above should be simple to adapt. If a new tree should be created with the mapped/filtered values, then feed these values back into a new tree (calling its add), or (in case of mapping) use the same recursive pattern of the above methods to create a new method that does not do yield, but creates a new tree while iterating the existing nodes, so the new tree has the same shape, but with mapped values.

Iterating through a Tree and getting certain children in C#

I'm currently working with a tree structure defined like this
public class TreeNode
{
private ObservableCollection<TreeItem> nodeItems;
private ObservableCollection<TreeNode> nodeChildren;
//public "NodeItems" and "NodeChildren" getters and setters
}
public class TreeItem
{
private bool isSelected;
private string Name;
//public "IsSelected" and "Name" getters and setters
}
public class Tree
{
private TreeNode rootNode;
//public getters and setters properties
}
and I'm trying to write a function or a public property that recursively gets all the nodeItems in the Tree that have isSelected == true and make it a flat collection.
So I wrote this function in the TreeNode class, that recursively navigates through the children:
public ObservableCollection<TreeItem> SelectedItems()
{
ObservableCollection<TreeItem> tempCollection = new ObservableCollection<TreeItem>();
if (nodeItems != null)
{
foreach (TreeItem item in nodeItems)
{
if (item.IsSelected == true)
{
tempCollection.Add(item);
}
}
}
if (nodeChildren != null)
{
foreach (TreeNode node in nodeChildren)
{
tempCollection.Concat(node.SelectedItem());
}
}
return tempCollection;
}
but it always returns an empty collection at the end.
How can I correct it, and maybe improve it (by using a Lambda expression or a property)?
The Concat function on the ObservableCollection does not modify any of the arguments. You have to assign the resulting object to your tempCollection.
if (nodeChildren != null)
{
foreach (TreeNode node in nodeChildren)
{
tempCollection = new ObservableCollection<TreeNode>(tempCollection.Concat(node.SelectedItem()));
}
}
EDIT: Alternatively, you can use an overloaded private method to not use so many temporary collections:
public ObservableCollection<TreeItem> SelectedItems()
{
ObservableCollection<TreeItem> toReturn = new ObservableCollection<TreeItem>();
SelectedItems(toReturn);
return toReturn;
}
private void SelectedItems(ObservableCollection<TreeItem> tempCollection)
{
if (nodeItems != null)
{
foreach (TreeItem item in nodeItems)
{
if (item.IsSelected == true)
{
tempCollection.Add(item);
}
}
}
if (nodeChildren != null)
{
foreach (TreeNode node in nodeChildren)
{
node.SelectedItems(tempCollection);
}
}
}
You can simplify your definition of a tree down to this:
public class Tree : ObservableCollection<Tree>
{
public ObservableCollection<TreeItem> nodeItems;
}
Now you can do this:
public IEnumerable<TreeItem> FlattenIsSelected(Tree tree)
{
return tree.nodeItems.Where(x => x.isSelected)
.Concat(tree.SelectMany(t => FlattenIsSelected(t)));
}
It's not much more difficult if you keep your current definitions.

Foreach Every Control on all forms

I want to manipulate all Controls within my form using a foreach loop, I currently am using the following method:
foreach (Control c in this.Controls)
{
ComponentResourceManager resourceManager = new ComponentResourceManager(typeof(Main));
resourceManager.ApplyResources(c, c.Name, new CultureInfo(lang));
}
The problem with this foreach, is that Controls within Containers aren't included.
How Can I include all the Controls within the Containers too?
I would like to do this in 1 or maybe 2 foreach loops.
Controls
Add the following class to your project:
public static class ControlExtensionMethods
{
public static IEnumerable<Control> GetOffsprings(this Control #this)
{
foreach (Control child in #this.Controls)
{
yield return child;
foreach (var offspring in GetOffsprings(child))
yield return offspring;
}
}
}
It will return all sub controls of the caller:
var offsprings = this.GetOffsprings();
You can use it in the loop:
foreach (Control c in this.GetOffsprings())
{
// Do action
}
Menu items
Add the following class to your project:
public static class MenuStripExtensionMethods
{
public static IEnumerable<ToolStripItem> GetSubItems(this ToolStrip #this)
{
foreach (ToolStripItem child in #this.Items)
{
yield return child;
foreach (var offspring in child.GetSubItems())
yield return offspring;
}
}
public static IEnumerable<ToolStripItem> GetSubItems(this ToolStripItem #this)
{
if (!(#this is ToolStripDropDownItem))
yield break;
foreach (ToolStripItem child in ((ToolStripDropDownItem) #this).DropDownItems)
{
yield return child;
foreach (var offspring in child.GetSubItems())
yield return offspring;
}
}
}
It will return all sub menu items of the caller:
var allMenuItems = this.menuStrip1.GetSubItems()
Make it recursive:
private static void ApplyResources(ComponentResourceManager resourceManager,
CultureInfo cultureInfo,
Control container)
{
foreach (var control in container.Controls)
{
resourceManager.ApplyResources(control, control.Name, cultureInfo);
ApplyResources(resourceManager, cultureInfo, control);
}
}
And use it like this:
var resourceManager = new ComponentResourceManager(typeof(Main));
var cultureInfo = new CultureInfo(lang);
ApplyResources(resourceManager, cultureInfo, this);

Depth first search using Queue

How do I do a depth first search using a Queue in c#?
The following is my datastructure:
public class Node
{
public string Name{get;set}
public IEnumerable<Node> Children{get;set;}
}
Now I have a collection of Node object each with children, which again has children and so on.
I want to access each node and convert it into a different form.
Something like the below:
public IEnumerable<IContent> BuildContentFrom(IEnumerable<Node> nodes)
{
var queue = new Queue<Node>(nodes);
while (queue.Any())
{
var next = queue.Dequeue();
yield return BuildContentFromSingle(next);
foreach (var child in next.Children)
{
queue.Enqueue(child);
}
}
}
public IContent BuildContentFromSingle(Node node)
{
var content = _contentFactory.Create(node);
return content;
}
The above does not give me depth first for some reason. Can you please help?
Depth-first search is implemented using a LIFO data structure, so you 'd need to swap the Queue for a Stack. Using a FIFO structure like a queue gives you BFS instead.
you can do it recursively
public IEnumerable<IContent> BuildContentFrom(IEnumerable<Node> nodes) {
foreach(var node in nodes){
yield node;
foreach(var c in BuildContentFrom(node.children)){
yield c;
}
}
}
This might become a problem with n-trees when n is large and/or the tree deep.
in which case you could use an accumulator
public IEnumerable<IContent> BuildContentFrom(IEnumerable<Node> nodes) {
if(!nodes.Any()) return Enumerable.Empty<IContent>();
var acc = new List<IContent>();
BuildContentFrom(nodes);
}
public IEnumerable<IContent> BuildContentFrom(IEnumerable<Node> nodes,
IList<IContent> acc) {
foreach(var node in nodes){
acc.Add(BuildContentFromSingle(node));
if(node.children.Any()) BuildContentFrom(node.children, acc);
}
}
Which is now tail recursive and if the compiler optimizes for that (a setting for C# as far as I remember) you will have no stack issues even with large trees.
Alternatively you can use a stack to collect the work you still need to perform
public IEnumerable<IContent> BuildContentFrom(IEnumerable<Node> nodes)
{
var stack= new Stack<Node>(nodes);
while (stack.Any())
{
var next = stack.Pop();
yield return BuildContentFromSingle(next);
foreach (var child in next.Children)
{
stack.push(child);
}
}
}
As an alternative, you could consider flattening the structure using recursion. Here's an example with a binary tree. It demonstrates a depth-first flattening traversal.
using System;
using System.Collections.Generic;
namespace Demo
{
public static class Program
{
static void Main(string[] args)
{
var tree = buildTree(5, true);
printTree1(tree);
Console.WriteLine("---------------------------------------------");
printTree2(tree);
}
// Print tree using direct recursion.
static void printTree1<T>(Node<T> tree)
{
if (tree != null)
{
Console.WriteLine(tree.Value);
printTree1(tree.Left);
printTree1(tree.Right);
}
}
// Print tree using flattened tree.
static void printTree2<T>(Node<T> tree)
{
foreach (var value in flatten(tree))
{
Console.WriteLine(value);
}
}
// Flatten tree using recursion.
static IEnumerable<T> flatten<T>(Node<T> root)
{
if (root == null)
{
yield break;
}
foreach (var node in flatten(root.Left))
{
yield return node;
}
foreach (var node in flatten(root.Right))
{
yield return node;
}
yield return root.Value;
}
static Node<string> buildTree(int depth, bool left)
{
if (depth > 0)
{
--depth;
return new Node<string>(buildTree(depth, true), buildTree(depth, false), "Node." + depth + (left ? ".L" : ".R"));
}
else
{
return new Node<string>(null, null, "Leaf." + (left ? "L" : "R"));
}
}
}
public sealed class Node<T>
{
public Node(Node<T> left, Node<T> right, T value)
{
_left = left;
_right = right;
_value = value;
}
public Node<T> Left { get { return _left; } }
public Node<T> Right { get { return _right; } }
public T Value { get { return _value; } }
private readonly Node<T> _left;
private readonly Node<T> _right;
private readonly T _value;
}
}
For your specific example, I think (without testing it) that you can do this:
public static IEnumerable<Node> Flatten(Node root)
{
foreach (var node in root.Children)
{
foreach (var child in Flatten(node))
{
yield return child;
}
}
yield return root;
}
Depending on whether you allow null nodes, you might need to add some null checking:
public static IEnumerable<Node> Flatten(Node root)
{
if (root != null)
{
foreach (var node in root.Children)
{
foreach (var child in Flatten(node))
{
if (child != null)
{
yield return child;
}
}
}
yield return root;
}
}

Expand selected node after refresh TreeView in C#

I have a treeview with many items
When I expand an item and its childs and after I called refresh method, that expanded item childs becomes collapsed.
Can you give me an idea how to store the selected node and after refresh, to call the Expand method again...
I tried :
TreeNode selectedNode = new TreeNode();
TreeNode selectedNode = SelectedTreeNode(); //method which takes selected node from TV
RestoreFolderTreeWithLastSelectedItem(); //method which initialise treeview object
//here I want to call Expand() method but it not exists to TreeNode.
For treeview, I used Windows.Controls.treeView namespace
I am beginner...
Thank you
I will explain you via images
I expanded all items:
If I press F5 or call Refresh function (RestoreFolderTreeWithLastSelectedItem();) then they will be collapsed like as:
instead of first image...
I'm using this with a WinForms TreeView. It saves the nodes expanded state between refreshes:
// Save the path of the expanded tree branches
var savedExpansionState = treeView1.Nodes.GetExpansionState();
treeView1.BeginUpdate();
// TreeView is populated
// ...
// Once it is populated, we need to restore expanded nodes
treeView1.Nodes.SetExpansionState(savedExpansionState);
treeView1.EndUpdate();
Here is the code to achieve this:
public static class TreeViewExtensions
{
public static List<string> GetExpansionState(this TreeNodeCollection nodes)
{
return nodes.Descendants()
.Where(n => n.IsExpanded)
.Select(n => n.FullPath)
.ToList();
}
public static void SetExpansionState(this TreeNodeCollection nodes, List<string> savedExpansionState)
{
foreach (var node in nodes.Descendants()
.Where(n => savedExpansionState.Contains(n.FullPath)))
{
node.Expand();
}
}
public static IEnumerable<TreeNode> Descendants(this TreeNodeCollection c)
{
foreach (var node in c.OfType<TreeNode>())
{
yield return node;
foreach (var child in node.Nodes.Descendants())
{
yield return child;
}
}
}
}
Again this is a very old issue, but again this might help.
It builds on the above samples, but also preserves the scroll position and selection, and written as an extension class.
These are restored as well as possible upon restore - that is, if the selected node has been removed, then its parent will be selected / scrolled to.
// To use:
//
// var expState = tv.GetExpandedNodesState(TreeView);
// TreeView.Nodes.Clear();
// ... reload...
// tv.RestoreTreeViewState(TreeView, expState);
public static class TreeViewExtensions
{
public static TreeViewState GetExpandedNodesState(this TreeView tree)
{
var expandedNodesList = new List<string>();
foreach (TreeNode node in tree.Nodes)
{
UpdateExpandedList(ref expandedNodesList, node);
}
return new TreeViewState(expandedNodesList, tree.TopNode, tree.SelectedNode);
}
public static void RestoreExpandedNodesState(this TreeView tree, TreeViewState state)
{
tree.BeginUpdate();
foreach (TreeNode node in tree.Nodes)
{
foreach (var nodeState in state.ExpandedNodes)
{
ExpandNodes(node, nodeState);
}
}
tree.TopNode = findNodeFromPath(tree, state.TopNodePath);
tree.SelectedNode = findNodeFromPath(tree, state.SelectedNodePath);
tree.Focus();
tree.EndUpdate();
}
static TreeNode findNodeFromPath(TreeView tree, string path)
{
if (string.IsNullOrWhiteSpace(path))
return null;
List<string> elements = path.Split(tree.PathSeparator.ToCharArray()).ToList();
TreeNode curNode = tree.Nodes.findByText(elements[0]);
if (curNode == null)
return null;
foreach (string element in elements.Skip(1))
{
if (curNode.Nodes.findByText(element) != null)
curNode = curNode.Nodes.findByText(element);
else
break;
}
return curNode;
}
static TreeNode findByText(this TreeNodeCollection tnc, string text)
{
foreach (TreeNode node in tnc)
if (node.Text == text)
return node;
return null;
}
static void UpdateExpandedList(ref List<string> expNodeList, TreeNode node)
{
if (node.IsExpanded) expNodeList.Add(node.FullPath);
foreach (TreeNode n in node.Nodes)
{
if (n.IsExpanded)
UpdateExpandedList(ref expNodeList, n);
}
}
static void ExpandNodes(TreeNode node, string nodeFullPath)
{
if (node.FullPath == nodeFullPath) node.Expand();
foreach (TreeNode n in node.Nodes)
{
if (n.Nodes.Count > 0)
ExpandNodes(n, nodeFullPath);
}
}
}
public class TreeViewState
{
public TreeViewState(List<string> expandedNodes, TreeNode topNode, TreeNode selectedNode)
{
this.ExpandedNodes = expandedNodes;
this.TopNodePath = topNode != null ? topNode.FullPath : null;
this.SelectedNodePath = selectedNode != null ? selectedNode.FullPath : null;
}
public readonly List<string> ExpandedNodes = null;
public readonly string TopNodePath = "";
public readonly string SelectedNodePath = "";
}
It's very simple.
First, before refreshing, we must store ids of expanded nodes:
//CollectExpandedNodes(tree.Nodes); - call of function
//this recursive function save ids of expanded nodes to expandedNodeIds
//List<int> expandedNodeIds = new List<int>(); - list for storage id
private void CollectExpandedNodes(TreeListNodes nodes)
{
foreach (TreeListNode node in nodes)
{
if (node.Expanded) expandedNodeIds.Add(node.Id);
if (node.HasChildren) CollectExpandedNodes(node.Nodes);
}
}
And then, after refreshing you tree, you must expand nodes whose IDs are stored in a expandedNodeIds:
expandedNodeIds.ForEach((id) =>
{
TreeListNode node = tree.FindNodeByID(id);
if (node != null) node.Expanded = true;
});
This is old post, but I think if someone will come here, this code fragment will be useful...
To save TreeView State possible with this simple code:
//you need to have 4 methods for it and call two of them...
//code where treeview needs to save and restore
var expState = GetAllExpandedNodesList(TreeView);
TreeView.Nodes.Clear();
//do something else...
RestoreTreeViewState(TreeView, expState);
//end of treeview save/restore section
private static void UpdateExpandedList(ref List<string> expNodeList, TreeNode node)
{
if (node.IsExpanded) expNodeList.Add(node.FullPath);
foreach (TreeNode n in node.Nodes)
{
if (n.IsExpanded) UpdateExpandedList(ref expNodeList, n);
}
}
private static List<string> GetAllExpandedNodesList(TreeView tree)
{
var expandedNodesList = new List<string>();
foreach (TreeNode node in tree.Nodes)
{
UpdateExpandedList(ref expandedNodesList, node);
}
return expandedNodesList;
}
private static void ExpandNodes(TreeNode node, string nodeFullPath)
{
if (node.FullPath == nodeFullPath) node.Expand();
foreach (TreeNode n in node.Nodes)
{
if (n.Nodes.Count >0) ExpandNodes(n, nodeFullPath);
}
}
private static void RestoreTreeViewState(TreeView tree, List<string> expandedState)
{
foreach (TreeNode node in tree.Nodes)
{
foreach (var state in expandedState)
{
ExpandNodes(node, state);
}
}
}

Categories

Resources