I'm having a strang problem with c# Winforms (not tried VB.NET admittingly) whereby I have a TabControl on a page, and 4 TabPages.
I have some authentication logic to show/hide these TabPages when showing the form after it's been minimised. This "hiding" logic will essentially remove the tabs, and re-insert them when the form authenticates.
So, First the application is minimised. I restore it, fail my authentication and so the tabs are removed. I minimise the application again, restore the window, pass the authentication and the tabs are inserted. However, the controls within the pages that are anchored to opposite sides (so left, right and top, bottom to allow them to stretch) appear to have broken. The top/left positions are ok, but the opposite position appears to have stretched off the visible page!
I'm guessing this is all related to the removal and additions of pages, but has anyone seen this before and know why this happens?? (and more importantly know a work around) :)
Just to note, my code to hide/show the tabs uses a function as follows: -
private void TabControlPageVisible(TabPage page, Boolean show)
{
if (show)
{
if (!tabControlMain.TabPages.Contains(page))
{
tabControlMain.TabPages.Insert(0, page);
page.ResumeLayout();
}
}
else
{
if (tabControlMain.TabPages.Contains(page))
{
page.SuspendLayout();
tabControlMain.TabPages.Remove(page);
}
}
}
Cheers! :)
are you using a layout method on each page or you're just positioning the controls? a (troublesome) solution is to store the position of each control. a much better idea would be to use a layout.
Related
I'm reading a Windows Forms book and I came to one example which is pretty confusing to me.
Here are two pictures, the first is the initial state, and the second is when the user click the Hide button.
This form contains two split containers, one horizontal, and one vertical, which is in the right panel of horizontal one.
The book says:
One of the best characteristics of docked designs is that they easily accommodate hidden
or modified controls. To implement
this design, two panels are placed in the left region of the
SplitContainer, one named pnlFileList and the other named pnlShow.
However, only one of these panels is shown at a time. The contents of
the rest of the window automatically resize themselves to accommodate
the additional view when it is displayed
private void cmdHide_Click(object sender, System.EventArgs e)
{
splitContainer1.Panel1Collapsed = true;
pnlShow.Visible = true;
}
private void cmdShow_Click(object sender, System.EventArgs e)
{
pnlShow.Visible = false;
splitContainer1.Panel1Collapsed = false;
}
And I made it, but the problem is with the button which appears when the left panel of the SplitContainer is collapsed.
I don't know where to put the panel "pnlShow"
If I put it on the right side of the horizontal SplitContainer control, it will disappear also.
Any suggestions?
The quote from the book doesn't seem accurate to me. You can't place pnlShow inside the "left region" of the SplitContainer because it will not be visible once you set the Panel1Collapsed property to true.
Instead, you can place the pnlShow on the left to the SplitContainer and set its Dock property to Left. Also, you don't seem to actually need a Panel in this case since it only contains one Button. You can simply use a Button only. Anyhow, your form would look something like this in design-time:
Then, your code should work fine.
Some remarks:
Of course, if you decided to use a button without a panel, you'd need to use YourButtonName.Visible instead of pnlShow.Visible.
If you found that the button (panel) on the left covers the SplitContainer, you just need to right-click on the SplitContainer and select "Bring to front".
It's preferred to use "btn" as a prefix for the Button name instead of "cmd". The latter was kind of widely used in the classic visual basic language, because it used to be called CommandButton. In the .NET world, the standard is to use "btn" instead.
Finally, based on what I mentioned in the last point above and the look of the screenshots in your question, this book seems to be quite outdated and was written based on the early versions of the .NET framework, so unless you have to study this book specifically, I would recommend you find a more recent book or tutorials.
Pre-warning, I'm new to C# and XAML, but I'm really enjoying Windows 10 UWP apps. I've got a question on how to appropriately handle a SplitView.
I've got a Main Page, in which I have a SplitView control. In the SplitView Content, I've added a Frame for navigation to other pages. I want to add the Hamburger button on the child page to open the SplitView on the Main Page, but I can't access the SplitView control from the child page. How can I make the SplitView control accessible so that the hamburger button within the sub-page can open the SplitView pane?
The alternative is to add a header in the Main Page and have a static hamburger button there, but I don't like this option as it makes handling the text header content more difficult. Another is to copy the SplitView to each page. I don't want to do this either.
Any advice would be fantastic! Thank you.
I would highly recommend you take your alternative option of including the hamburger button in the main page. Users always expect it to be in the same location every time and changing this approach will probably result in a bad user experience.
You also don't want to be repeating code and thus you don't want to recreate the button on every page as well as any additional functionality like the open/close commands.
Rather than referencing elements from one page to another, a better practice is to keep things loosely coupled. This can be done with a messenger plugin which sends an event from one page to the other which can give it instructions on what you want to do. That way the other page only has to listen for the event instead of holding strong references. To streamline some of this process you could inherit from a base class which implements the messenger functionality.
That would provide a solution to your button and your header text situations but setting them up is out of the scope of this question. Depending on the size of you app and your goals, you might like to look into existing frameworks which helps in designing maintainable apps. A good Mvvm framework I would recommend checking out is MvvmCross which also cross platform and contains a messenger plugin.
Good luck with your app.
I found that solution :
In the MainPage, in your SplitView pane button method, add a SplitView reference as parameter in Navigate() :
private void SlitViewPaneButton_Tapped(object sender, TappedRoutedEventArgs e)
{
var frame = contentFrame;
Page page = frame?.Content as Page;
if (page?.GetType() != typeof(ChildPage))
{
frame.Navigate(typeof(ChildPage), SplitViewName);
}
}
In your ChildPage.xaml.cs :
protected override void OnNavigatedTo(NavigationEventArgs e)
{
SplitView sv = new SplitView();
sv = e.Parameter as NavigateControls;
}
You can now do sv.IsPaneOpen = false, in your ChildFrame code.
Note : if you want to pass several Controls, create a Class with these Controls as variables, and use an instance as parameter.
As stated above, it is better to keep your hamburger button in your main page for a couple of reasons. One is the consistency mentioned above. Second, you would have to recreate the hamburger button in each of your content pages instead of just once in the MainPage.xaml. Additionally, keep in mind, there are different kinds of interactions with the SplitView menu in terms of how it pops in and out and how it is displayed, all listed below.
Inline – When the menu pane is opened, it pushes the content over. When it’s closed, the content goes back to its original location
Overlay – When the menu pane is opened, it lays on top of the content. When it’s closed, it is invisible.
Compact Overlay – When the menu pane is opened, it lays on top of the content. When it’s closed, the pane is still visible in Compact Mode.
Compact Inline – When the menu pane is opened, it pushes the content over. When it’s closed, the content goes back to its original position but the pane is still visible in Compact Mode.
You can also see a quick intro into the SplitView here.
http://jamesqquick.com/windows-10-splitview-intro/
I want to create simple wizard with 3 pages
Page 1 have just next button
Page 2 have next and previous
Page 3 have previous and finish
I have created the pages and add to them needed buttons and in the events I have call to the next pages, for instance in page one in the button click I added the following code
private void Button_Click(object sender, RoutedEventArgs e)
{
p2 = new Page2();
NavigationService.Navigate(p2);
}
In the main window cs I have changed the inheritance to NavigationWindow instead of Window and in the xaml also. Currently its working but I have 3 questions.
The pages which displayed is part of the main window, how can i avoid it, since when I run it the buttons place is not like I put in the designer? It was changed.
The button currently in the Grid, should I put them in different control (the button place should be like any wizard in the left buttom of the page) ?
How can I avoid the navigation arrows in the page right upper screen?
Thanks!
To answer your questsions in reverse,
3. How can I avoid the navigation arrows in the page upper right screen?
I have an opensource library http://winchrome.codeplex.com/ that re-styles navigation windows in several ways. For example these are all NavigationWindow s
In short you just style the NavigationWindow to only show the parts you want.
2.The button currently in the Grid, should I put them in different control (the button place should be like any wizard in the left buttom of the page) ?
If you look at the styles from WinChrome then you will see that it is just a case of rebuiliding the UI as you want and providing a ContentPresenter to hold your pages. e.g. the VS2012 style applies lots of styles on the window but avoids adding back and forward buttons., whereas the Win7 style rebuilds the back and forwards in a Win7 Style.
If you do this however you will need a means of passing your enabled or visible states to the buttons outside the pages. Take a look at http://www.codeproject.com/Articles/8197/Designer-centric-Wizard-control for how to do this in Winforms. In WPF you could either derive from your Pages to create WizardPage classes with CanBack, CanNext or IsFinish properties, or alteratively define attached properties to do the same (There are examples of how to do this in VS2012.cs where we define the glow color)
And finally
1. The pages which displayed is part of the main window, how can i avoid it, since when I run it the buttons place is not like I put in the designer? It was changed.
I'd need to see some code to comment on how you've done it, but if you look at any of the demo programs in WinChrome then you can see how I've done it without problems.
Good luck!
I'm making a program to generate code for me, and I'm fashioning the UI after Game Maker due to how easy the interface is. It has a SplitContainer with Panel1 containing a TreeView and Panel2 containing an arbitrary amount of self-contained windows (real windows, not some hacky workaround). I wanted to use user-controls to store the controls I use to modify things, but I can't figure out any way to put it in a window inside the splitContainer's Panel2. Can anyone help me?
Here's a good example:
http://i.stack.imgur.com/CG6kO.png
Those two sprite property windows are what I'm trying to do.
i think what you are looking for is called mdi-container
however the only real mdi container i've seen so far (in .NET) is a form ... sadly no panel or something similar...
but if you just want the "window in a window" effect: simply create your new form, set the TopLevel property of that instance to false, and add the instance to your form/panel/splitcontainer/whatever like any other usual control
You could try using an MDI form and to implement your TreeView control, check out some sort of docking panel. I've used this one in the past (http://sourceforge.net/projects/dockpanelsuite/).
It is very flexible. You set up one of these dockpanel forms, docked to the left of your MDI form. It will always be "on top" and the user can resize it exactly like the splitter control on a form. If you like, it can also has an "autohide" feature which may or may not be desirable in your case.
It can then contain you treeview, which can load all the MDI Child forms you like.
You'll find you're not fighting how "Windows" really want to behave and things will run a lot more smoothly.
Put it into the Panel2's Control collection via the Add() method, apply coordinates, anchor and docking programmaticaly.
I did similar thing once, and for that reason, I have ReplaceControl method, which I paste below:
static public void ReplaceControl(Control ToReplace, Form ReplaceWith) {
ReplaceWith.TopLevel=false;
ReplaceWith.FormBorderStyle=FormBorderStyle.None;
ReplaceWith.Show();
ReplaceWith.Anchor=ToReplace.Anchor;
ReplaceWith.Dock=ToReplace.Dock;
ReplaceWith.Font=ToReplace.Font;
ReplaceWith.Size=ToReplace.Size;
ReplaceWith.Location=ToReplace.Location;
ToReplace.Parent.Controls.Add(ReplaceWith);
ToReplace.Visible=false;
}
Only thing left to do is to create some control manually on the form, as the placeholder for your Form. Use label, for example.
From How to implement a-form-inside-a-form with runtime embedded forms switching?
Let's just say that I have many controls on my Form, and when a User clicks on one of them, its height will expand. This means that, currently, when this clicked-control expands, other controls below it will become overlapped by the expanded control.
But what I want to happen, is for each Control below the expanded control to slide down, so that they are below the expanded control again.
I know how to handle sliding, but I just don't know how to make every control except for one move everytime a given control is moved.
Any help at all is greatly appreciated, thank you!
This is what I was thinking:
void newOrderReceived(object sender, EventArgs e)
{
foreach(Control OrderNotificationBox in OrdersPanel.Controls)
{
if(OrderNotificationBox is NotificationBox) // Checks to see if the control is a NotificationBox
{
// Add my code to slide controls down.
}
}
}
But... How do I know if the control is below the expanded control?
Is this how I should go about changing the location of all controls below the expanded control?
Edit: Just had a thought, to check to see if a NotificationBox is below the Expanded NotificationBox, see revised code below:
void newOrderReceived(object sender, EventArgs e)
{
foreach(Control OrderNotificationBox in OrdersPanel.Controls)
{
if(OrderNotificationBox is NotificationBox) // Checks to see if the control is a NotificationBox
{
if(OrderNotificationBox.Location.Y <= ExpandedNotificationBox.Location.Y + ExpandedNotificationBox.Size.Width)
{
// Add my code to slide controls down.
}
}
}
}
But would this be sufficient? Currently, this is working, so I guess I just answered my own question. But, isn't there a better way to do this? A more elegant/efficient way?
Here's a sample of how it should look:
FlowLayoutPanel provides you with dynamic layout where you can resize any control in it and all below controls will slide automatically. There are many strategies to using groups/columns of flow layout panels to be able to achieve the desired look for the whole form. Some googling will reveal some of these.
For instance in the form above, resizing the button1 control simply flows all the below controls to further down on the form. You can try that at the design time also. Drop the form a flow layout panel, drop 3-4 control in the container and start experimenting..
For each expandable content use Panel.
Dock your panels one under another (Use panel1.Dock = DockStyle.Top. For the very bottom panel use panel1.Dock = DockStyle.Fill).
Place your child controls inside of each expandable panel, set inner controls' Anchor properties accordingly.
When you expand one panel, the rest of the panels will adjust automatically. You don't need to code for this. You will only change Height of a panel that you currently expand.
What you need is some kind of 'ExplorerBar' functionality. There are several control libraries that offer that, and I found the article here on the CodeProject that has it for free.