I have a method called OpenURL() and recordHistory() with the following definitions:
public string OpenURL(string url)
{
//get index of current tab
int tabIndex = BrowserWindow.TabControlE.SelectedIndex;
//create instance of History class
History H = new History();
//call recordHistory() method to record the url and tabIndex
H.recordHistory(url, tabIndex);
}
public void recordHistory(string url, int tabIndex)
{
//print the tabIndex
Console.WriteLine("Tab is: "+tabIndex);
}
The scenario is: I would like to record history for each tab.
However, I am facing some unexpected behavior from TabControl.SelectedIndex.
When the first tab is created, the output in recordHistory() is:
Tab is: -1
When I refresh the page (call OpenURL() on the same tab), this time the output in recordHistory() is:
Tab is: 0
It seems that the first time a tab is created the TabControl.SelectedIndex value is wrong. This goes away after refreshing the page. How do I correct this so that it displays the correct value?
EDIT: Adding the recordHistory() call.
In class BrowserWindow:
private void BrowserWindow_Load(object sender, EventArgs e)
{
TabControl1 = new TabControl();
TabControl1.SelectedIndexChanged += TabControl1_SelectedIndexChanged;
Tab Tab1 = new Tab(tab_counter, getHomePageURL());
TabControl1.Controls.Add(Tab1.createNewTab());
this.Controls.Add(TabControl1);
}
In class Tab:
class Tab
{
int tab_ID;
String tab_URL;
TabPage page;
public Tab(int tab_ID, String tab_URL)
{
this.tab_ID = tab_ID;
this.tab_URL = tab_URL;
}
public TabPage createNewTab()
{
//Create a new tab
page = new TabPage("New Tab");
page.Text = this.tab_URLE;
page.Controls.Add(R1);
R1.Text = OpenURL(this.tab_URLE);
return page;
}
}
The flow goes: BrowserWindow_Load() --> createNewTab() --> OpenURL() --> recordHistory()
The problem is with your BrowserWindow_Load event. Change the order of the last 2 statements and it should work. Like this:
private void BrowserWindow_Load(object sender, EventArgs e)
{
TabControl1 = new TabControl();
TabControl1.SelectedIndexChanged += TabControl1_SelectedIndexChanged;
Tab Tab1 = new Tab(tab_counter, getHomePageURL());
this.Controls.Add(TabControl1);
TabControl1.Controls.Add(Tab1.createNewTab());
}
Related
i have been creating a cefsharp browser in C#. i have made it so you can have multiple tabs and it loads the pages correctly. however, i cannot seem to find how i can rename the tab to the name of the page.
this is the code in the load event for form1.cs:
Cef.Initialize();
toolTip1.SetToolTip(button1, "Settings");
TabPage tab = new TabPage();
Tab newtab = new Tab();
newtab.Show();
newtab.TopLevel = false;
newtab.Dock = DockStyle.Fill;
tab.Controls.Add(newtab);
tabControl1.TabPages.Add(tab);
i have tried:
private void myBrowser_isLoading(object sender)
{
myBrowser.Parent.Parent.Text = myBrowser.Title;
}
but that doesn't work.
then this is the code for tab.cs:
public Tab()
{
InitializeComponent();
// Start the browser after initialize global component
InitializeChromium();
}
public CefSharp.WinForms.ChromiumWebBrowser myBrowser;
public bool nav = new bool();
public void InitializeChromium()
{
myBrowser = new CefSharp.WinForms.ChromiumWebBrowser("http://www.google.com");
this.Controls.Add(myBrowser);
myBrowser.Dock = DockStyle.Fill;
myBrowser.Parent = panel2;
if (nav == true)
{
myBrowser.Load(textBox1.Text);
nav = false;
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
Cef.Shutdown();
}
again, i am using c# with the latest build of cef sharp(or atleast the one installed from the nuget package manager).
In your tab function in form1.cs, you need to add a title changed function like this
browser.TitleChanged += OnBrowserTitleChanged;
you also need to specify what browser is and set dockstyle to fill like this
ChromiumWebBrowser browser = new ChromiumWebBrowser("google.com");
tab.Controls.Add(browser);
browser.Dock = DockStyle.Fill;
now for the OnBrowserTitleChanged, you will need an EventArg which will tell the tab to have the document title in this format
this.InvokeOnUiThreadIfRequired(() => browserTabControl.SelectedTab.Text = args.Title);
this will add the document title to the tabcontrol browserTabControl is the name of the tabcontrol you will have to change browserTabControl to whatever name you have for the tabcontrol. Also the code you have does not belong with cef initialize. you need to create an addNewTab method with all the functions that will be processed when you want to add a new tab. Also, you cannot use a panel if you want to have tabs. you need a tabcontrol
Background
I have a main form that has a tableLayoutPanel. Within that I have three panel, a header, footer and left side bar. In the remaining space I add and remove usercontrols this one in the example is called ctrlmanagepreset.
Within these usercontrols I have controls. Namely a Listsbox s, that i'm trying to add items too.
I am getting the items from an xml file that does contain items and reading them in to an object list. The name of each object is then added to the listbox.
All of the Controls are accessable as I've made them public. I think it might be due to the way i create and add them?
Question
Why aren't the Listboxes updating, showing the added items?
Code
Button click event that creates usercontrol
public void btnManage_Click(object sender, EventArgs e)
{
tableLayoutPanel.Controls.Add(new ctrlManagePresets () { Dock = DockStyle.Left }, 1, 1);
PopulateCreateJob();
}
Method that Populates Listbox
public void PopulateCreateJob()
{
ctrlManagePresets ctrlmanagepresets = new ctrlManagePresets();
//read in contents of xml file
if (File.Exists(JoblistXmlFilepath))
{
XmlSerializer deserializer = new XmlSerializer(typeof (List<Favourite>));
TextReader reader = new StreamReader(JoblistXmlFilepath);
//create list of old fave objects
var xmlList = (List<Favourite>) deserializer.Deserialize(reader);
reader.Close();
if (xmlList.Count > 0)
{
foreach (Favourite t in xmlList)
{
//add favourite objects to combobox
try
{
ctrlmanagepresets.lbCreateJob.Items.Add(t.Name);
}
catch
{
MessageBox.Show(#"There is an object with no name in the XML.", #"Message",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
}
ctrlmanagepresets.lbCreateJob.Refresh();
}
else
{
ctrlmanagepresets.lbCreateJob.Items.Add(#"Settings File Not Found");
ctrlmanagepresets.lbCreateJob.Enabled = false;
ctrlmanagepresets.lbCreateJob.BackColor = Color.DarkRed;
}
}
You are not adding the items to the instance of the control that you add to your tableLayoutPanel.
Just make your PopulateCreateJob return the instance that is built and intialized with the xml data
public void btnManage_Click(object sender, EventArgs e)
{
ctrlManagePresets ctrl = PopulateCreateJob();
ctrl.Dock = DockStyle.Left;
tableLayoutPanel.Controls.Add(ctrl, 1, 1);
}
public ctrlManagePresets PopulateCreateJob()
{
ctrlManagePresets ctrlmanagepresets = new ctrlManagePresets();
// current code that initialize the instance of your control
....
// return the control instance initialized to the caller
return ctrlmanagepresets;
}
I have an array of button created dynamically, suppose 8 buttons, what I want is that when I click a particular button its background picture is changed and the name of button is stored in a linked list. When I click the same button again the background picture goes back to the original and the button name is deleted from linked list. Now I am able to do the first part, the second click is not working as I want it to.
Basically it's a datastructures project (shopping store) therefore I am using linked list, I have a linked list whose content is displayed through picture boxes[] and labels. Here what i am trying to do is when I click the picture box, the content of that particular node is added to a new linked list (added to the cart) and when I click on the picturebox again that particular item is deleted from the linked list (removed from the cart). Clicking it for the first time it is doing what i want it to do but the second click is not really working.
It's a datastructures project therefore I can't really use any built in classes for linked list, I had to write all methods myself and I did and they work.
cb[i].Click += (sender, e)=>{
if (flag == 0) {
// Console.WriteLine(obj.Retrieve(index).NodeContent);
// Console.WriteLine(obj.Retrieve(index).number);
inv.Add(obj.Retrieve(index).NodeContent, obj.Retrieve(index).number);
bill += Convert.ToInt32(obj.Retrieve(index).number);
cb[index].Image = Image.FromFile(#"F:\uni work\3rd semester\project images\rcart.jpg");
flag++;
}
else if (flag == 1)
{
// Console.WriteLine(bill);
bill -= Convert.ToInt32(obj.Retrieve(index).number);
// Console.WriteLine(bill);
inv.Delete(index);
cb[index].Image = Image.FromFile(#"F:\uni work\3rd semester\project images\cart.png");
flag--;
}
Since you are using a LinkedList it does have a Contains Method and a Remove Method that take a string. You haven't specified exactly what your problem is this should work. When you assign images to a control you loose the information that tells you what Image it is.
public partial class Form1 : Form
{
LinkedList<String> myList = new LinkedList<String>();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
for (int i = 0; i < 8; i++)
{
Button b = new Button() { Height = 30, Width = 70, Location = new Point(i, 50 * i),Name = "NewButton" + (i + 1).ToString() , Tag=i};
b.Click += b_Click;
this.Controls.Add(b);
}
}
void b_Click(object sender, EventArgs e)
{
Button b = (Button)sender;
if(myList.Contains(b.Name)) //Check if button is in the List then Change Picture and remove
{
b.BackgroundImage = Properties.Resources.Peg_Blue;
myList.Remove(b.Name);
}
else
{
b.BackgroundImage = Properties.Resources.Peg_Red;
myList.AddLast(b.Name);
}
}
}
Why not create a class for each button, containing the two images and switch between them on each click?
I have a method as follows:
private List<ProjectFile> PopUpModifiedFiles(List<ProjectFile> ModifiedFiles)
{
this.lblModifiedFilesMessage.Text = "Below files are modified in the Source Server and will be archived with latest version. Please select any files if they are to be retained with older version in archive";
DataTable dtModifiedFiles = new DataTable();
dtModifiedFiles.Columns.Add("FileName");
foreach (ProjectFile modifiedFile in ModifiedFiles)
{
DataRow drFileName = dtModifiedFiles.NewRow();
drFileName["FileName"] = modifiedFile.FileName;
dtModifiedFiles.Rows.Add(drFileName);
}
gvPopUpModifiedFiles.DataSource = dtModifiedFiles;
gvPopUpModifiedFiles.DataBind();
this.JsContent = string.Format("setPopupPosition('{0}');setPopupBackgroundPosition('{1}');", this.divPopUpFiles.ClientID, this.divPopUpBackGround.ClientID);
this.PopUpPanel.Visible = true;
this.divPopUpBackGround.Visible=true;
this.divPopUpFiles.Visible = true;
this.lblModifiedFilesMessage.Visible = true;
this.gvPopUpModifiedFiles.Visible = true;
List<ProjectFile> archiveFiles = new List<ProjectFile>();
return archiveFiles;
}
This Method show a pop-up in which I have a grid view and a button.
On click of that button I have to return the files.
My button click event is like this:
protected void btnOk_Click(object sender,EventArgs e)
{
PopUpPanel.Visible = false;
ProjectFile filesToArchive;
List<ProjectFile> filesToArchiveAfterUserSelection = new List<ProjectFile>();
foreach (GridViewRow gvrow in gvPopUpModifiedFiles.Rows)
{
CheckBox chk = (CheckBox)gvrow.FindControl("chkFileSelect");
if (chk != null & chk.Checked)
{
filesToArchive = new ProjectFile();
filesToArchive.FileName = gvrow.Cells[1].Text;
filesToArchiveAfterUserSelection.Add(filesToArchive);
}
}
}
How can I return the values on click of the button to my method?
One more thing that I am facing in this is pop-up is not visible after calling the method Pop-Up method Files. It is coming after the execution of entire code. I called this Pop-Up some where. This Pop-Up is not visible.
PHenix_yu says right.
U can put "List filesToArchiveAfterUserSelection = new List();" out of this button event and in this class.
If you want to keep the return value after close your pop-up window,you can define a class like the below:
public class FileStore
{
public static List<ProjectFile> filesToArchiveAfterUserSelection = new List<ProjectFile>();
}
If you only want to get the return value when pop-up window open,you can change filesToArchiveAfterUserSelection as a class member in your pop-up window class
I am making an application where i am opening wpf pages in tab control. But i am able to open same page again and again in tabcontrol. I want that if once page is opened it can't be opened again and it should get focused on tabcontrol if i try to open it again. i did following code but not working. I am using a custom closableTabItem Usercontrol.
private void Set_Fee_Click(object sender, RoutedEventArgs e)
{
// Adding page to frame and then adding that frame to tab item and then adding tab item to main tab.
FeeStructure feePage = new FeeStructure();
_closableTab = new ClosableTabItem();
_formFrame = new Frame();
_formFrame.Content = feePage;
_closableTab.Content = _formFrame;
_closableTab.Header = "Set Fee Structure";
if (!mainTab.Items.Contains(_closableTab))
{
mainTab.Items.Add(_closableTab);
_closableTab.Focus();
}
else
{
_closableTab.Focus();
}
}
private void Database_RecoveryBackup_Click(object sender, RoutedEventArgs e)
{
// Adding page to frame and then adding that frame to tab item and then adding tab item to main tab.
DbRecoveryBackup dbRecBack = new DbRecoveryBackup();
_closableTab = new ClosableTabItem();
_formFrame = new Frame();
_formFrame.Content = dbRecBack;
_closableTab.Content = _formFrame;
_closableTab.Header = "Data Base";
if (!mainTab.Items.Contains(_closableTab))
{
mainTab.Items.Add(_closableTab);
_closableTab.Focus();
}
else
{
_closableTab.Focus();
}
}
It'll never happen, what you want because you're creating a new instance of ClosableTabItem everytime, hence it is unique everytime, so .Items.Contains will never work in this case because it matches items using object.Equals.
Now, Since you said in question that you only want one instance of ClosableTabItem, then
using Linq, you can check if in the items there exist any item of type ClosableTabItem,
...
// Here we're checking the array 'Items',
// if it contains any item whose type is 'ClosableTabItem'
if (!mainTab.Items.Any(item => item is ClosableTabItem)))
...