How to add events after load back by XamlReader - c#

I created a class Rtb which is to create a new RichTextBox, below is the constructor and list
public Rtb()
{
newRTB = new RichTextBox();
newRTB.IsReadOnly = true;
newRTB.MouseDoubleClick += new MouseButtonEventHandler(newRTB_MouseDoubleClick);
reqName = "Box" + NextID.ToString();
newRTB.Name = reqName;
}
List<Rtb> rtbeditor = new List<Rtb>();
I want to click the menu, add a BlockUIContainer, and a new richtextbox inside the container, see below
private void menuReq_Click(object sender, RoutedEventArgs e)
{
BlockUIContainer newBlockUC = new BlockUIContainer();
newBlockUC.Margin = new Thickness(50, 10, 50,10);
Bigwin.Document.Blocks.Add(newBlockUC); //Bigwin is a big richtextbox
rtbeditor.Add(new Rtb());
Rtb newRichTB = new Rtb();
newBlockUC.Child = newRichTB.newRTB;
}
Then I save it by using XamlWriter, the problem is XamlWriter can not save event, so i have to add the event back when loading it, see below
private void LoadRtfFile(string path)
{
FileStream fs = new FileStream(path, FileMode.Open);
FlowDocument doc = XamlReader.Load(fs) as FlowDocument;
Bigwin.Document = doc;
fs.Close();
foreach (var rtb in rtbeditor)
rtb.MouseDoubleClick += req1_MouseDoubleClick; //add event to every richtextbox
}
But the doubleclick event is not added by this solution, I think the last part of codes has problem. So how to add events to every created richtextbox?

You are subscribing to MouseDoubleClick on Rtb, not on Rtb.newRTB.

Related

Get the text from clicked Hyperlink

I created some Hyperlinks using the code below:
public Class_List()
{
InitializeComponent();
StackPanel myStackPanel = new StackPanel();
TextBlock txt = new TextBlock();
txt.Foreground = Brushes.Black;
txt.FontFamily = new FontFamily("03SmartFontUI");
txt.FontSize = 25;
txt.Margin = new Thickness(0, 5, 0, 5);
Run run = new Run(className);
Hyperlink link = new Hyperlink(run);
link.Click += Link_Click;
txt.Inlines.Add(link);
}
Now, I want to get the text of the hyperlink and store it on string s:
private void Link_Click(object sender, RoutedEventArgs e)
{
string s = (sender as Hyperlink).Inlines.ToString();
Class_Page class_page = new Class_Page();
NavigationService.Navigate(class_page);
}
However instead of the hyperlink text, I got
System.Windows.Documents.InlineCollection
You're getting that type because you are actually accessing the entire collection of Inlines rather than the Inline you're looking for. The fastest way to access the Run's text you're using as the first Inline in the Hyperlink's InlineCollection is to do this:
((sender as Hyperlink).Inlines.FirstInline as Run).Text;

Opening in RichTextBox rather than Tab name

// add a module tab
private void add_mod_Click(object sender, EventArgs e)
{
int TabCount = 0;
int? index = searchIndex(mod_add_textbox.Text);
if (index == null)
{
RichTextBox new_rich = new RichTextBox();
new_rich.Dock = DockStyle.Fill;
TabPage NewPage = new TabPage();
TabCount += 1;
string DocumentText = mod_add_textbox.Text;
NewPage.Name = DocumentText;
NewPage.Text = DocumentText;
NewPage.Controls.Add(new_rich);
mod_tab.TabPages.Add(NewPage);
}
else
{
mod_tab.SelectedIndex = Convert.ToInt32(index);
}
}
private async void btn_file_note_Click(object sender, EventArgs e)
{
using(OpenFileDialog ofd = new OpenFileDialog() { Filter="Text Documents|*.txt", ValidateNames = true, Multiselect = false })
{
if(ofd.ShowDialog() == DialogResult.OK)
{
using (StreamReader sr = new StreamReader(ofd.FileName))
{
mod_tab.SelectedTab.Text = await sr.ReadToEndAsync();
}
}
}
}
The problem I am getting is that when I try to open a document it is opening it into the tab name rather than the rich text box inside the tab. I have changed the "mod_tab.SelectedTab" part to the name of the rich text box within the tab however I want it so whichever tab the user has selected it opens in there. Any suggestions? thank you.
You assigned the value to the Text property of selected tab. Instead you should assign the value to Text property of RichTextBox or use Load method of RichTextBox to load content. for example:
this.richTextBox1.Text = ....
Also when you create the tab and RichTextBox dynamically like you ar doing in your code, you can find it this way:
//It means: Find all RichTextBox control which are children of mod_tab.SelectedTab
//And return first of them.
var rtb = this.mod_tab.SelectedTab.Controls.OfType<RichTextBox>().FirstOrDefault();
rtb.Text = ...
Also this way:
//It means get the first child control of mod_tab.SelectedTab
//And convert it to RichTextBox.
var rtb = this.mod_tab.SelectedTab.Controls[0] as RichTextBox;
rtb.Text = ...

How to create click event for dynamically created user controls in C#?

I'm creating a Windows Universal App which contains a ListView filled with User-Controls. User-Controls are added to ListView dynamically during runtime, based on the elements from the database.
public void ShowFavorites()
{
using (SQLite.Net.SQLiteConnection conn = new SQLite.Net.SQLiteConnection(new SQLite.Net.Platform.WinRT.SQLitePlatformWinRT(), (Application.Current as App).DBPath))
{
var Favorites = conn.Table<Favorites>();
lvFavorites.Items.Clear();
foreach (var fav in Favorites)
{
FavoriteItem favItem = new FavoriteItem();
favItem.Favorite = fav;
lvFavorites.Items.Add(favItem);
}
}
}
So how can i create an event that that triggers when the user-control is pressed?
When you create the control, all you need to do is simply link the control to a new event:
// Dynamically set the properties of the control
btn.Location = new Point((lbl.Width + cmb.Width + 17), 5);
btn.Size = new System.Drawing.Size(90, 23);
btn.Text = "Add to Table";
// Create the control
this.Controls.Add(btn);
// Link it to an Event
btn.Click += new EventHandler(btn_Click);
Then, when you (in this case) click on the newly added button, it will call your btn_Click method:
private void btn_Click(object sender, EventArgs e)
{
//do stuff...
}
I got it working even for items with diffrent text etc.
I gonna explain it based on a button beeing added to a panel.
You need to have a List<> in which you store the items, in this case buttons.
List<Button> BtList = new List<Button>();
and I also have a Panel in this case.
Panel PanelForButtons = new Panel();
Here is my code I hope it helps you:
void AddItemToPanel()
{
//Creating a new temporary item.
Button TempBt = new Button();
TempBt.Text = "Hello world!";
//Adding the button to our itemlist.
BtList.Add(TempBt);
//Adding the event to our button.
//Because the added item is always the last we use:
PanelForButtons.Controls.Add(BtList.Last());
BtList.Last().Click += MyButtonClicked;
}
And here is the event:
void MyButtonClicked(object sender, EventArgs e)
{
//First we need to convert our object to a button.
Button ClickedButton = sender as Button;
//And there we have our item.
//We can change the text for example:
ClickedButton.Text = "The world says: \"Hello!\"";
}

c# get control from another void/form (eventHandler)

In form1 I created simple form called formhaslo.
I created in formhaslo control called listBoxhaslo
Now, I want to create MouseDoubleClick Event to listBoxhaslo.
I have problem with getting listBoxhaslo from formhaslo to form1.
Can you take a look at this code, please (check out comments):
public partial class Form1 : Form
{
Form formhaslo = new Form();
...
...
...
public void buttonLoadPassForBAKFile_Click(object sender, EventArgs e)
{
int i = 0;
string path = #"Backups";
formhaslo.StartPosition = FormStartPosition.CenterScreen;
ListBox listBoxhaslo = new ListBox();
listBoxhaslo.Location = new System.Drawing.Point(0, 30);
listBoxhaslo.Left = (formhaslo.ClientSize.Width - listBoxhaslo.Width) / 2;
using (FileStream fsSbHaslo = new FileStream(path + #"\BAKPass._pass", FileMode.Open, FileAccess.Read, FileShare.Read))
{
using (StreamReader srhaslo = new StreamReader(fsSbHaslo, Encoding.Default))
{
string line;
while ((line = srhaslo.ReadLine()) != null)
{
listBoxhaslo.Items.Add(line);
i++;
}
srhaslo.Close();
}
formhaslo.Controls.Add(listBoxhaslo);
formhaslo.Controls.Add(label1);
listBoxhaslo.MouseDoubleClick += new MouseEventHandler(listBoxhaslo_MouseDoubleClick); // <---here is EventHandler
formhaslo.Show();
}
}
void listBoxhaslo_MouseDoubleClick(object sender, MouseEventArgs e)
{
if ((listBoxhaslo.SelectedItem) != null) // <--listBoxhaslo does not exist in current context
{
PassForBakFile = (listBoxhaslo.SelectedItem.ToString());
formhaslo.Hide();
}
}
I know that this error must be there because im doing it wrong but I don't know how to do it.
The listBoxhaslo doesn't exists because it was declare within the scope of first function which is not visible to the second function of your event listBoxhaslo_MouseDoubleClick. For you to make it work you need to declare listBoxhaslo variable outside of your function. You could declare it after formhaslo near top. Or another way to accomplish this is to cast sender to ListBox within your event.
void listBoxhaslo_MouseDoubleClick(object sender, MouseEventArgs e)
{
var listBoxhaslo = (sender as ListBox);
if (listBoxhaslo.SelectedItem != null)
{
PassForBakFile = (listBoxhaslo.SelectedItem.ToString());
formhaslo.Hide();
}
}
I haven't tried the code but I think it will do.

rtf to textblock

When I try to set a textblock with rtf it gives a funny output is there a way to display rtf in a textblock if so how?
private void button1_Click(object sender, RoutedEventArgs e)
{
TextRange tr = new TextRange(richTextBox1.Document.ContentStart,
richTextBox1.Document.ContentEnd);
MemoryStream ms = new MemoryStream();
tr.Save(ms, DataFormats.Rtf);
string rtfText = ASCIIEncoding.Default.GetString(ms.ToArray());
textBlock1.Text = rtfText;
Edit update:
I can do this:
private void button1_Click(object sender, RoutedEventArgs e)
{
TextRange tr = new TextRange(richTextBox1.Document.ContentStart,
richTextBox1.Document.ContentEnd);
MemoryStream ms = new MemoryStream();
tr.Save(ms, DataFormats.Rtf); // does not contain a definition
string rtfText = ASCIIEncoding.Default.GetString(ms.ToArray());
MemoryStream stream = new MemoryStream(ASCIIEncoding.Default.GetBytes(rtfText));
this.richTextBox2.Selection.Load(stream, DataFormats.Rtf);
But I really hate the richtextbox is there no other controls that can hold rich text formatting? Or is there a way in which you can tell a certain control to display rtf?
You can't use a TextBlock to display RTF text. But if it's ok to show the text in a FlowDocumentScrollViewer, you could copy it this way:
public MainWindow()
{
InitializeComponent();
richTextBox.Document = new FlowDocument();
flowDocumentScrollViewer.Document = new FlowDocument();
}
private void CopyDocument(FlowDocument source, FlowDocument target)
{
TextRange sourceRange = new TextRange(source.ContentStart, source.ContentEnd);
MemoryStream stream = new MemoryStream();
XamlWriter.Save(sourceRange, stream);
sourceRange.Save(stream, DataFormats.XamlPackage);
TextRange targetRange = new TextRange(target.ContentStart, target.ContentEnd);
targetRange.Load(stream, DataFormats.XamlPackage);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
CopyDocument(richTextBox.Document, flowDocumentScrollViewer.Document);
}
Get an overview of Flow Documents here.
This is going to give you the whole FlowDocument but the good news is that does include the markup. I assume that is what you are looking for
string textMarkUp = System.Windows.Markup.XamlWriter.Save(richTextBox1.Document);
Debug.WriteLine(textMarkUp);
Sample output
<Paragraph>asdfas<Run FontWeight="Bold">adsfasd;lkasdf</Run><Run FontStyle="Italic" FontWeight="Bold">alskjfd</Run></Paragraph>
I needed Text Block because it can expand to contents and we can set wrap as none. I am storing rtf string in database. I added the string to RichTextBlock and then used its document to get the inline.
Dim stream As New IO.MemoryStream(System.Text.ASCIIEncoding.[Default].GetBytes("{\rtf1\ansi\ansicpg1252\deff0\deflang1040{\fonttbl{\f0\fnil\fcharset0 Microsoft Sans Serif;}}{\colortbl ;\red255\green255\blue255;}\viewkind4\uc1\pard\cf1\f0\fs29 RIGO NOTIZIA 1 TESTO TESTO TESTO\fs17\par}"))
Dim RichTextBox1 As New RichTextBox()
RichTextBox1.Selection.Load(stream, DataFormats.Rtf)
Dim pr As New System.Windows.Documents.Paragraph()
pr = RichTextBox1.Document.Blocks(0)
Dim tre As Int32 = pr.Inlines.Count
TextBlock1.Inlines.Add(pr.Inlines(0))
RichTextBox is used just for conversion, final control is FlowDocumentScrollViewer, so I've ended up with slightly simplified function:
public static class FlowDocumentScrollViewerEx
{
static public bool ReadFromFile(this FlowDocumentScrollViewer fDoc, String rtfFilePath)
{
RichTextBox retext = new RichTextBox(); // Just an intermediate class to perform conversion
retext.Document = new FlowDocument();
fDoc.Document = new FlowDocument();
TextRange tr = new TextRange(retext.Document.ContentStart, retext.Document.ContentEnd);
if (!File.Exists(rtfFilePath))
return false;
using (var fs = new FileStream(rtfFilePath, FileMode.OpenOrCreate))
{
tr.Load(fs, DataFormats.Rtf);
fs.Close();
}
MemoryStream ms = new MemoryStream();
System.Windows.Markup.XamlWriter.Save(retext, ms);
tr.Save(ms, DataFormats.XamlPackage);
TextRange flowDocRange = new TextRange(fDoc.Document.ContentStart, fDoc.Document.ContentEnd);
flowDocRange.Load(ms, DataFormats.XamlPackage);
return true;
} //ReadFromFile
} //class FlowDocumentScrollViewerEx
Usage is quite trivial:
flowDocument.ReadFromFile(#"license.rtf");

Categories

Resources