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!
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/
For those who are very familiar with C# or VB.NET using the UserControl component in the .NET Framework (which is the hottest framework in my opinion), you were used to adding several buttons that preview different user controls as follows:
1) First you would prepare an appropriate user interface (contains 3 buttons and a single panel on the right area to view each user control after clicking one of the added buttons).
2) Adding 3 user controls from the solution explorer...
3) Inserting the content on each user control...
4) Implementing code for the 3 buttons on the frmMain.cs as the following (for this implementation we will be implementing the "Welcome" button carrying the object name as welcomeBtn, and the rest will have identical code but different user control names instead):
private void welcomeBtn_Click(object sender, EventArgs e)
{
//Clear up everything from the panel if any item exist(s)...
mainPanel.Controls.Clear();
//Create a new instance of a user control for the button...
UserControl1_Welcome welcome = new UserControl1_Welcome();
//Show up the created instance of the user control
mainPanel.Controls.Add(welcome);
}
5) Finally, the program will end up initially like this when running:
http://i.stack.imgur.com/OENwG.png
** Usage of the program **
When you click on the "Welcome" button for example, the result should be expected to be like this:
http://i.stack.imgur.com/iCyo3.png
... and when you click on a different button, lets say "License Agreement" button, you would expect to see something other than your current selection.
MAIN QUESTION
How can we bring the simplicity of Windows Forms in QT CREATOR by applying the "QDockWidget"?
I have tried inserting the QDockWidget component with no problems, but when I try to do the equivalent .NET code for adding the QWidget inside the QDockWidget:
ui->dockWidget->setWidget(myWidget);
which I think is equivalent to this line of code in C#.NET (correct me if I'm wrong here):
ui.Controls.Add(myWidget);
After using this code, my program won't crash nor shows anything running...
P.S. I'm sorry for linking the images, I don't have 10 reputation for making them show up...
What I want is to have a program that does the same thing with the C# example (showing a user control based on the click of a button).
If you want to show a particular widget based on a button click, I suggest to use a QStackedWidget
A simple example would be like this:
// In the constructor of your CustomWidget
// Create your buttons
QPushButton* firstButton = new QPushButton("First Button", this);
QPushButton* secondButton = new QPushButton("Second Button", this);
QPushButton* thirdButton = new QPushButton("Third Button", this);
// Create your (custom) widgets
QLabel* firstPageWidget = new QLabel("First Label", this);
QLabel* secondPageWidget = new QLabel("Second Label", this);
QLabel* thirdPageWidget = new QLabel("Third Label", this);
// Add them to the stackWidget
/*QStackedWidget* */ m_stackedWidget = new QStackedWidget(this);
m_stackedWidget->addWidget(firstPageWidget);
m_stackedWidget->addWidget(secondPageWidget);
m_stackedWidget->addWidget(thirdPageWidget);
// Insert buttons and stackWidget to CustomWidget
QVBoxLayout* layoutStack = new QVBoxLayout();
layoutStack->addWidget(m_stackedWidget);
QVBoxLayout* layoutButtons = new QVBoxLayout();
layoutButtons->addWidget(firstButton);
layoutButtons->addWidget(secondButton);
layoutButtons->addWidget(thirdButton);
QHBoxLayout* layout = new QHBoxLayout();
layout->addLayout(layoutButtons);
layout->addLayout(layoutStack);
setLayout(layout);
// Connect button clicks to slots
connect(firstButton, SIGNAL(clicked()), this, SLOT(onFirstButtonClicked()));
connect(secondButton, SIGNAL(clicked()), this, SLOT(onSecondButtonClicked()));
connect(thirdButton, SIGNAL(clicked()), this, SLOT(onThirdButtonClicked()));
Then you change the currently visible widget in the slots:
void CustomWidget::onFirstButtonClicked() {
m_stackedWidget->setCurrentIndex(0);
}
void CustomWidget::onSecondButtonClicked() {
m_stackedWidget->setCurrentIndex(1);
}
void CustomWidget::onThirdButtonClicked() {
m_stackedWidget->setCurrentIndex(2);
}
Note that if you want the button clicks just to simply change some text (as opposed to change the visible widget), you probably better use a QTextEdit instead of a QStackedWidget, and in the slots call setText("....");
If you have a lot of buttons, you'd better use QSignalMapper to limit the number of slots.
Also, I didn't get why you mentioned QDockWidget since they have a quite specific usage:
The QDockWidget class provides a widget that can be docked inside a QMainWindow or floated as a top-level window on the desktop.
QDockWidget provides the concept of dock widgets, also know as tool palettes or utility windows. Dock windows are secondary windows placed in the dock widget area around the central widget in a QMainWindow.
If you simply want a separate window, you're probably looking for a QDialog
How to do this with QtDesigner:
First you would prepare an appropriate user interface (contains 3 buttons and a single QStackedWidget on the right area to view each user control after clicking one of the added buttons).
Adding 3 pages for the user controls in the stack (+ one for the "empty" page if you really need that). If you want to design the Controls in separate UI Files / Only in Code (instead of all controls in your MainFrame), you would add plain QWidgets and promote them to the appropriate specific widget type
Inserting the content on each user control...
Implementing code for the 3 buttons on the frmMain.cpp/.h as the following (for this implementation we will be implementing the "Welcome" button carrying the object name as welcomeBtn, and the rest will have identical code but different user control names instead):
void FrmMain::on_welcomeBtn_clicked() {
ui->stack->setCurrentWidget(ui->welcomeWidget);
}
Select the "empty" page at as the current page in the designer, so the program will end up initially like this when running: (your screenshot)
When you click on the "Welcome" button for example, the result should be expected to be like this: (your second screenshot)
In my opinion, Miki's answer is the only correct approach to this use case (using a QStackedWidget).
For sake of completeness, I'll demonstrate how the same Clear and Add method as used in .NET is done in Qt:
// Assume controlPanel is a QWidget where you want to place the items
// Assume that controlPanel has set a layout (e.g. QHBoxLayout)
// Clear: Remove all Items from layout
QLayoutItem *child;
while ((child = controlPanel->layout()->takeAt(0)) != NULL) {
delete child;
}
// Now widgets are still there, but not layouted. Delete them explicitly
foreach (QWidget * w, controlPanel->findChildren<QWidget*>()) {
w->deleteLater();
}
// Now controlPanel is cleared
// Add new control
controlPanel->layout()->addWidget(new MyNewControlWidget);
First is, we can not force how other framework works to another one. Each framework has its flow and design.
What I am understand is you want to show another widget to the main window.
If you want to use the QDockWidget, its says on the documentation like this :
void QDockWidget::setWidget(QWidget * widget)
Sets the widget for the dock widget to widget.
If the dock widget is visible when widget is added, you must show() it explicitly.
Note that you must add the layout of the widget before you call this function; if not, the widget will not be visible.
Please share here you code of myWidget, so we can try to help you to figure out what is wrong.
On my side, I can achieve it by add the QVboxLayout on your ui->dockwidget and add QLabel with emtpy string and when you want to show myWidget just call ui->dockwidget->vboxlayout->replaceWidget(label, myWidget);
My goal
I am working on a project in C# using Visual Studio 2013. The project is one that I intend to contain a lot of pages. These pages are all linked together using buttons. My problem is that I cannot come up with an efficient and elegant solution for this.
My attempts
So far I have came up with two potenial solutions to my problem. First I added extra forms and then on button press I hid the current form and displayed the new form, like so:
Form2 frm = new Form2();
frm.Show();`
Form1.Hide();
While this does work, I have two problems with it.
My project will end up with hundreds of forms
The transition between forms looks sloppy. I am aiming for a browser like transition by where all navigation occurs on one window, without opening and closing others.
The second potential solution I tried incorporated the use of Panels. So I essentially created each page on a different Panel. Then the appropriate panel was shown upon a button press and the rest were hidden. Like this:
private void button1_Click(object sender, EventArgs e)
{
mainMenuPanel.Hide();
submenuPanel1.Show();
submenuPanel2.Hide();
submenuPanel3.Hide();
submenuPanel4.Hide();
}
This is exactly what I was looking for however my issue with it is that managing the vast amount of panels quickly became a nightmare. Editing the controls on a Panel that was hidden behind 9 other Panels and as the number of panels in my project was only going to grow - this does not seem like the ideal solution in its current form.
In my head I thought there maybe an option in Visual Studio 2013 that allows me to 'hide' the Panels I am not using on the form, or drag them off the form temporarily. Is that an option in Visual Studio.
If not do any of you know a more efficient and manageable way of achieving this?
Thanks in advance.
If you are stuck using WinForms, your best bet is probably using UserControls. you can actually extend the UserControl class out to be a "page" ie: UserControlPage. This makes the form much simpler in function, but you will need to do some finicky work with handling events /passing data if the controls need to talk to each other.
if you aren't nailed into using Winforms, WPF supports all of this natively, and has wonderful tools for building all the pages you would need, and storing/populating your data, and propagating events.
If you want to have single form with changing content, and you don't want to mess up with panels in one form, then solution is user controls. You will be able to create them dynamically and add to form controls. Also there is no mess, because your form will be very simple - you can have single 'placeholder' control which will be used to dock user control which is currently displayed (e.g. panel control):
private void ShowContent(Control content)
{
placeHolderPanel.Controls.Clear(); // clear current content
placeHolderPanel.Controls.Add(content); // add new
content.Dock = DockStyle.Fill; // fill placeholder area
}
Usage:
private void button1_Click(object sender, EventArgs e)
{
ShowContent(new FooUserControl());
}
You could subclass the Panel class and create as many of those custom panels as needed, then they would be inserted on your Main Form, and managed as you described.
The advantage is that you would be able to individually edit them as a separate user control.
The drawback is that you lose direct event handling of controls on those panels from the main form. You can still define your own events on those panels and delegate the individual control events.
There's always a trade-off somewhere.
Cheers
I am using FlipView control for flipping through various pages i.e. *.XAML pages. I am using ObservableCollection of Page class. Now one page among those pages contains AppBar, but that AppBar can be open in any other XAML page from collection also. How can I prevent the opening of AppBar in all pages ?
Easy Explanation:- I have four XAML pages.
(1) MainPage.xaml (Contains only FlipView and ObservableCollection of Page class)
(2) PageWithAppBar.xaml (AppBar is in this page)
(3) PageWithoutAppBar.xaml
(4) PageWithoutAppBar2.xaml
Now through flipview, when I flip on PageWithoutAppBar.xaml or PageWithoutAppBar2.xaml and press right click then AppBar of PageWithAppBar.xaml become visible so I don't want that thing, how can I prevent that ?
What I have tried till now ?
I have created function to check in which page the AppBar should be visible.
I tried to set
Visibility = Collapsed,
IsOpen = false,
this.BottomAppBar = null,
IsEnable = false
then also it appears
It looks like the Page.BottomAppBar applies to the main container page - regardless of where it is declared. Given this, I'm not sure it is a good idea to use AppBars this way.
Perhaps you may want to create your own control that behaves like an appbar and make it work the way you want? Have a look at :WinRT XAML Toolkit on Codeplex . There is a CustomAppBar control in there, which might work for you.