In .net MDI application the menu of child form automatically is merged to the menu of parent form.
Is there a way to do similar thing with the tool bars.The concept is to send the toolbar of active child to the parent toolbar stripe.
I found http://community.devexpress.com/forums/p/5696/24663.aspx but could not achieve it.
It can be done if following way .
More detail could be found in this blog. Both forms should have a toolstrip.
//In Parent form
protected override void OnMdiChildActivate(EventArgs e)
{
base.OnMdiChildActivate(e); //REQUIRED
HandleChildMerge(); //Handle merging
}
private void HandleChildMerge()
{
ToolStripManager.RevertMerge(tsParent);
IChildForm ChildForm = ActiveMdiChild as IChildForm;
if (ChildForm != null)
{
ToolStripManager.Merge(ChildForm.ChildToolStrip, tsParent);
}
}
public partial class frmChild : Form, IChildForm
{...}
interface IChildForm
{
ToolStrip ChildToolStrip { get; set; }
}
Related
I'm working on a C# console/winforms desktop app. It monitors some local drive properties and displays a status message on a user defined schedule via Task Scheduler. Multiple schedules can be saved by the user. Below are the actions taken to select/activate a particular saved schedule (the screenshots are sized at 50% and consolidated into a single graphic):
Screenshot A: click on “Change Active” button to call child form
Screenshot B: select a schedule from Combobox and click Activate
Selected Schedule which closes the child form, passing the selected
schedule for processing.
Screenshot C – result using Close()method:
The schedule definition screen is populated with the selected
schedule’s details including (if needed) calling a different child
form BUT the select active schedule form in not actually closing
before the parent form starts the processing for populating the data; Child1 only closes after Child2 is closed by clicking Save or Cancel.
Screenshot D – result using Hide()method: working as intended
Relevant code (I think)
public interface IselectSchedule
{
void SelectSchedule(string sName);
}
/// Parent form
public partial class DefineSched : Form, IDates, IDoWs, IselectSchedule
{
/// calling Child1
private void ChangeActvLBLasBTN_Click(Object sender, EventArgs e)
{
SetActvSchedule callSetActvSched = new SetActvSchedule(this);
callSetActvSched.StartPosition = FormStartPosition.Manual;
callSetActvSched.Location = new Point(this.Left + 45, this.Top + 25);
callSetActvSched.ShowDialog();
}
}
/// Child1 form
public partial class SetActvSchedule : Form
{
IselectSchedule _callingForm;
public SetActvSchedule(IselectSchedule caller)
{
InitializeComponent();
_callingForm = caller;
}
/// form content
private void SaveBTN_Click(Object sender, EventArgs e)
{
this.Close(); // not achieving my objective but Hide does
_callingForm.SelectSchedule(_sname);
}
}
/// back in Parent form
public void SelectSchedule(string sName)
{
_sName = sName;
bool useDB = false;
SetActvDisplay(useDB);
EditSaved(useDB);
}
private void EditSaved(bool useDB)
{
/// populate parent form data & call Child2
SelectDoW callSelectDoWs = new SelectDoW(this, det, det2);
callSelectDoWs.StartPosition = FormStartPosition.CenterParent;
callSelectDoWs.ShowDialog(owner: this);
/// ready for editing
I’ve researched/understand the Hide vs Close decision and think Close is appropriate here. My question is since Close() precedes returning to the parent form why isn’t that action completed before the parent form starts processing the passed info?
Thanks in advance for any insights.
Whilst I believe I nearly got the multi-thread approach suggested above to work I ran into a cross-Threading error I couldn’t resolve. Upon further consideration I may have been pursuing an unnecessarily complicated solution to achieve a very simple objective; present the user with some options and act on their selection.
The simple solution utilizes a public static field in the parent form that is set in the child form after which the child is cleanly closed and control returns to the parent form:
/// Parent form
public partial class DefineSched : Form
{
public static string _sName;
/// calling Child
private void ChangeActvBTN_Click(Object sender, EventArgs e)
{
SetActvSchedule callSetActvSched = new SetActvSchedule();
callSetActvSched.ShowDialog();
ActvSchedOptions();
}
}
/// Child1 form
public partial class SetActvSchedule : Form
{
private void SaveBTN_Click(Object sender, EventArgs e)
{
DefineSched._sName = _sname;
this.Close();
}
}
/// back in Parent form
ActvSchedOptions()
{
/// series of conditional statements
This approach circumvents the need for the Interface and avoids overloading the UI thread. I suspect it’ll not be considered a particularly elegant solution but it has one redeeming virtue: it works flawlessly for the task at hand.
In Xamarin Forms if you activate the navigation bar, that show you the title of the page and an arrow to use as a back button, when you have the screen reader activated and the back button is on focus, the talkback (for Android) says "unlabeled button".
I know how to set the Accessibility Name of general elements, but I don't know how to get the back button element, since it is not an istance.
If you're using Shell Navigation, create a CustomShellRenderer
[assembly: ExportRenderer(typeof(AppShell), typeof(CustomShellRenderer))]
namespace Droid.Renderers.CustomAppShell
{
public class CustomShellRenderer : ShellRenderer
{
protected override IShellToolbarAppearanceTracker CustomToolbarAppearanceTracker()
{
return new CustomShellToolbarAppearanceTracker(this);
}
}
}
namespace Droid.CustomShell
{
public class CustomShellToolbarAppearanceTracker : ShellToolbarAppearanceTracker
{
public override void SetAppearance(AndroidX.AppCompat.Widget.Toolbar toolbar, IShellToolbarTracker toolbarTracker, ShellAppearance appearance)
{
base.SetAppearance(toolbar, toolbarTracker, appearance);
toolbar.NavigationContentDescription = "Custom Label Description”; // Set label here
}
}
}
I am trying to develop a program in which it could create forms and add controls to it at runtime.
It also should be able to save, (Open and Edit) the forms created with the new controls added it at Runtime.The Application starts In the Main form.
CODE BEHIND MAIN Form
private void Btn_CREATE_FORM_Click(object sender, EventArgs e)
{
Form_Properties fp = new Form_Properties();
fp.Show();
}
private void BTn_ADD_BTN_Click(object sender, EventArgs e)
{
/// WHAT CODE SHOULD I ENTER TO ADD BUTON TO NEW FORM
}
Basically the main form is used to create/open/save new forms and add controls to it.
When the user clicks on Create New Form button the user will be presented with the following form (FORM_PROPERTIES) in which the user can customize the name, width and height of the new form.
CODE BEHIND FORM_PROPERTIES Form
public partial class Form_Properties : Form
{
public Form_Properties()
{
InitializeComponent();
}
String form_name;
int form_width;
int form_height;
private void Btn_OK_Click(object sender, EventArgs e)
{
form_name = TBox_NAME.Text;
form_width = Convert.ToInt32(TBox_WIDTH.Text);
form_height = Convert.ToInt32(TBox_HEIGHT.Text);
New_Form nf = new New_Form();
nf.Text = form_name;
nf.Width = form_width;
nf.Height = form_height;
nf.Show();
}
}
The following image shows what happens at runtime based on the code I have written so far.
ISSUES
Need help to Write Code
To add controls to new form created.
To Save/Open/Edit Functionalities.
I also need to know the method to access properties of added controls at runtime.
eg: If the user adds a text box to the NEW FORM and decides to type some text in it, I need a method to save that text.
Is there a way for me to name the added controls?
It seems you want to build some kind of WinForms' form designer. Your program would be similar to Glade (though Glade is much more powerful).
I'm afraid the question is too broad, though. There are many questions to answer, for example, how do you describe the created interface.
While Glade uses XML, you can choose another format, such as JSON. Let's say that you have a TextBox with the word "example" inside it.
{ type:"textbox" text:"example" }
It seems you want to add your components to the form as in a stack. Maybe you could add its position. For example, a form containing a label
("data"), a textbox ("example"), and a button ("ok"), would be:
{
{ pos:0, type:"label", text:"data" },
{ pos:1, type:"textbox", text:"example" },
{ pos:2, type:"button", text:"ok" },
}
But this is just a representation. You need to a) store this when the form is saved, and b) load it back when the form is loaded.
For that, you will need a class representing the components, such as:
public class Component {
public override string ToString()
{
return string.Format( "position:{0}, text:{1}", this.Position, this.Text );
}
public int Position { get; set; }
public string Text { get; set; }
}
public class TextBoxComponent: Component {
public override string ToString()
{
return base.ToString() + "type:\"textbox\"";
}
}
...and so on. This is a big task, I'm afraid, with no simple answer.
I am working on xamarin.forms. I need to detect the event of tab being changed either by swapping left or right or by clicking without using custom renderer
I tried below event but it is firing in both cases when child page being pushed or tab being changed. how can i get isolated event of tab being changed
public class MyTabbedPage : TabbedPage
{
public MyTabbedPage()
{
this.CurrentPageChanged += CurrentPageHasChanged;
}
protected void CurrentPageHasChanged(object sender,EventArgs e)
{
var pages= Navigation.NavigationStack;
if (pages.Count > 0)
{
this.Title = pages[pages.Count - 1].Title;
}
else
this.Title = this.CurrentPage.Title;
}
}
This issue I am facing is: In below screenshot part1 is Homepage(title="Diary") & part2 is Childpage(title="Homework") when I change tab & again come to first tab than navigationbar title getting changed "Homework" to "Diary"(Screeshot2)
As you are on your tabbed page already you can literally just do the following
public partial class MyTabbedPage : TabbedPage
{
public MyTabbedPage()
{
InitializeComponent();
CurrentPageChanged += CurrentPageHasChanged;
}
private void CurrentPageHasChanged(object sender, EventArgs e) => Title = CurrentPage.Title;
}
if you want to use the sender you can do the following
public partial class MyTabbedPage : TabbedPage
{
public MyTabbedPage()
{
InitializeComponent();
CurrentPageChanged += CurrentPageHasChanged;
}
private void CurrentPageHasChanged(object sender, EventArgs e)
{
var tabbedPage = (TabbedPage) sender;
Title = tabbedPage.CurrentPage.Title;
}
}
Or if you can elaborate on what you are trying to do exactly I can give a better answer as I do not know what it is that you are trying to do exactly
I don't think you can achieve what you want to do, at least not like this. The event behaves the way it does and as described: it is fired whenever the current page changes, also for children.
That being said, I think you should focus on implementing the functionality you want with the tools we have. I can't really deduce from your code what you are trying to do, but it looks like you want to change the title? When a tab is changed? Why not just make some kind of condition to only do it for certain pages? For example when the page is contained in the Children collection?
What I'm trying to do it load some information from a database.
To do this I open a form that lists everything that can be loaded.
When you click load I want to pass the ID back to the original form.
However I can't seem to be able to call a method in that form.
Any help would be appreciated.
I would flip this around:
Make the selection form into a modal dialog that is created and displayed by the form where you want to load something
Expose the selection made in the dialog through a property or method in the dialog form
This way the selection form will be decoupled from the caller, and can be reused wherever it makes sense without the need to modify it.
In the selection dialog form class:
public string GetSelectedId()
{
return whateverIdThatWasSelected;
}
In the calling form:
using(var dlg = new SelectionDialogForm())
{
if (dlg.ShowDialog() == DialogResult.OK)
{
DoSomethingWithSelectedId(dlg.GetSelectedId());
}
}
You could add a property to your form class and reference it from your other form.
eg.
public class FormA : Form
{
private string _YourProperty = string.empty;
public string YourProperty
{
get
{
return _YourProperty;
}
set
{
_YourProperty = value;
}
}
}
public class FormB : Form
{
public void ButtonClick(object sender, EventArgs args)
{
using (FormA oForm = new FormA)
{
if (oForm.ShowDialog() == DialogResult.OK)
{
string Variable = oForm.YourProperty;
}
}
}
You just need to set your property on a button click on form A then you can access it from form B
}
Why not create a public property for the selected item in the dialog form, something like this.
public int SelectedItemId {get;private set;}
//In your item selected code, like button click handler..
this.SelectedItemId = someValue;
Then just open the form as a Dialog
//Open the child form
using (var form = new ChildForm())
{
if (form.ShowDialog(this) == DialogResult.OK)
{
var result = form.SelectedItemId;//Process here..
}
}
The proper way to do this is to introduce a Controller class which is used by both forms. You can then use a property on the Controller, when that is set will trigger the NotifiyPropertyChanged event.
see INotifyPropertyChanged for more info