How do I switch pages within a WPF application? - c#

I have a WPF application and I cannot figure out a way to switch pages, even create multiple pages. All of the questions related to this topic only show how to switch, not create AND switch.
I have already tried to look up the solution, but no proper answer shows up.

Try
this.NavigationService.Navigate(new PageName());
Or
this.NavigationService?.Navigate(new PageName()); //To check if it's not null
Edit:Sorry, I didn't understand your question correctly.
As I know, you can't just create and navigate to a page. Why can't you just create a page, design it however you want, and then navigate?
Edit2: After some research, I found that you can create your own class and inherit it from Window class.
public class MyPage: Window
{
this.WindowStyle = WindowStyle.SingleBorderWindow;
//Add grid
this.RootGrid = new Grid()
{
//Add TextBox
TextBox TextBox_Test = new TextBox()
{ Text = "ABC",
Background = Brushes.Yellow,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Top
};
this.RootGrid.Children.Add(TextBox_Test);
}
}
You can add rows/columns as well.
this.RootGrid.RowDefinitions.Add(new RowDefinition() { Height = new GridLength(20) });
this.RootGrid.ColumnDefinitions.Add(new ColumnDefinition() { Width= new GridWidth(20) });
Then you can navigate to MyPage page as I told.
Hope this helps.

Related

Getting list of checked radiobuttons in .net

TLDR; Looking for a method to retrieve all radiobuttons by means of something like this... (psudo)
List<RadioButton> btn = new List<RadioButton>;
btn = stackPanel.getAllRadioButtons()
I am currently building a little quiz application in C#. I have functions that add the required GUI elements to a groupbox. I would like to know if there is any way that I can loop through the created elements (for instance radio buttons) to see which are checked.
Here is one of the functions along with how they are added to the window.
private void tfQ(string questionBody)
{
StackPanel questionPanel = new StackPanel{Orientation = Orientation.Vertical};
questionPanel.Children.Add(new Label { Content = questionBody });
GroupBox group = new GroupBox();
RadioButton trueRadio = new RadioButton();
trueRadio.Content = "True";
RadioButton falseRadio = new RadioButton();
falseRadio.Content = "False";
questionPanel.Children.Add(trueRadio);
questionPanel.Children.Add(falseRadio);
group.Content = questionPanel;
mainStack.Children.Add(group);
}
Constructor:
public quiz()
{
tfQ("This is a true/false question");
Window w = new Window();
w.Content = mainStack;
w.Show();
}
I have found many ways to do it in the C# scripting format
(using the Control function ...)
var checkedButton = container.Controls.OfType<RadioButton>()
.FirstOrDefault(r => r.Checked);
but I have not yet found a "programmatic" way of doing it. I have considered changing the type of void tfQ to a StackPanel, but that only helps me to easier loop through the stack panels, althought that only partly solves me problem - allows me to easier loop through the StackPanels but I still don't know how to get the RadioButtons on a panel.
P.S I am very new to C# - with experience in Java/C/C++/Python
I made use of the following code to cast the content into a new groupbox and stackpanel, respectively.
if (child is GroupBox)
{
if ((child as GroupBox).Content is StackPanel)
{
StackPanel d = (StackPanel)((GroupBox)child).Content;
}
}
This allowed me to cast the content into a local copy of a control. It may not be the best way - I'm sure it is very inefficient to be honest. Solved the problem.

Xamarin / C# : How to iterate through Array/List DataMember passed to the viewCell without using inner ListView

I've been advised that Xamarin doesn't support nested ListViews.. I trying to build social app, in which the post might have several images and comments.
The feed page will be basically a ListView of the posts. While I cannot use a listView within the post (which is a viewCell), I tried to use Grid for the images instead, and another Grid for Comments. Both Images and Comments can be Lists, Arrays or ObservableCollections in the "post" Class.
Now I need to make foreach loop of this array/list, adding images with source bound to array item. But it seems to me, I couldn't use the data passed to the viewCell in C# (can only be used in Xaml layout).
Anybody has any ideas how to solve this.
[DataContract]
Public class post {
[DataMember]
List<comment> commentContainer {get; set;}
[DataMember]
List<String> imageContainer {get; set;}
}
in Xaml of cellView
<Grid x:Name="imagesGrid" IsVisible="{Binding isImage}" BindingContext="{Binding imageContainer}">
here I need to iterate the list of image in c# if possible - runtime- !
</Grid>
You are right to say that you shouldn't use nested ListViews in Xamarin.Forms, virtualization goes out the window and scrolling/gestures will be hard to handle.
However, i think this design in Xamarin.Forms will be fraught with problems. Xamarin.Forms ListView is a very specific beast and wont play well with very complicated layouts. My gut feeling is you want to do this in Native Views maybe or at the very least design this entirely in code. Anyway that is just my gut feel.
Have it be noted, i would shy away from this design and make it simple for your self by doing like WhatsApp does, and use a Template Selector and break apart multiple images and posts with a DataTemplateSelecto. Then you Don't have to worry about complicated layouts.
However, if you have your heart set on more complicated layouts inside ListView (be warned there be dragons) though you can take a look at this, Cell Appearance As noted i would be more inclined to this entirely in Code apposed to an ad-hock Xaml solution
public class CustomCell : ViewCell
{
public CustomCell()
{
//instantiate each of our views
var image = new Image ();
StackLayout cellWrapper = new StackLayout ();
StackLayout horizontalLayout = new StackLayout ();
Label left = new Label ();
Label right = new Label ();
...
//add views to the view hierarchy
horizontalLayout.Children.Add (image);
horizontalLayout.Children.Add (left);
horizontalLayout.Children.Add (right);
cellWrapper.Children.Add (horizontalLayout);
View = cellWrapper;
}
}
And set it like this
public partial class ImageCellPage : ContentPage
{
public ImageCellPage ()
{
InitializeComponent ();
listView.ItemTemplate = new DataTemplate (typeof(CustomCell));
}
}
Also checkout Grid
You can build one in code like this
var grid = new Grid();
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star)});
grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star)});
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star)});
grid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star)});
var topLeft = new Label { Text = "Top Left" };
var topRight = new Label { Text = "Top Right" };
var bottomLeft = new Label { Text = "Bottom Left" };
var bottomRight = new Label { Text = "Bottom Right" };
grid.Children.Add(topLeft, 0, 0);
grid.Children.Add(topRight, 0, 1);
grid.Children.Add(bottomLeft, 1, 0);
grid.Children.Add(bottomRight, 1, 1);

Group related controls on ToolStrip so they are always visible together

I have an application that has a tool strip with related controls set apart by ToolStripSeparaters. It looks something like this:
However, when the window size shrinks, some of the controls get moved to a little drop-down section. Unfortunately, this can split related controls, for example in the screenshot below, the "Filter by ID" label, the associated textbox for the ID, and "Clear Filter" button are no longer shown together.
If controls have to be moved to the drop-down, I'd prefer to have related controls move together. Is there a way to group related controls together on a ToolStrip? Or perhaps a better way of dealing with this sort of scenario?
I tried using the LayoutCompleted event move all of the controls to the overflow area if any of them are in the overflow.
private void toolStrip1_LayoutCompleted(object sender, EventArgs e)
{
var filterGroup = new List<ToolStripItem> { lblFilter, txtFilter, btnClearFilter };
if (filterGroup.Any(x => x.IsOnOverflow))
{
filterGroup.ForEach(x => x.Overflow = ToolStripItemOverflow.Always);
}
}
This seems to work fine, but I haven't found a good way to show them again when the window size is increased. I tried both the Resize and Layout events of the ToolStrip with the following code:
var filterGroup = new List<ToolStripItem> { lblFilter, txtFilter, btnClearFilter };
filterGroup.ForEach(x => x.Overflow = ToolStripItemOverflow.AsNeeded);
You could use a ToolStripControlHost to group a winforms TextBox and Label. E.g.
public class ToolStripLabelTextBox : ToolStripControlHost {
public Label Label { get; private set; }
public TextBox TextBox { get; private set; }
public ToolStripLabelTextBox(String labelText) : base(new FlowLayoutPanel { FlowDirection = FlowDirection.LeftToRight, WrapContents = false, AutoSize = true, AutoSizeMode = AutoSizeMode.GrowAndShrink, Padding = Padding.Empty, Margin = Padding.Empty }) {
Label = new Label { Text = labelText, AutoSize = true, Anchor = AnchorStyles.Top | AnchorStyles.Bottom, TextAlign = System.Drawing.ContentAlignment.MiddleCenter };
TextBox = new TextBox();
FlowLayoutPanel panel = (FlowLayoutPanel) Control;
panel.Controls.Add(Label);
panel.Controls.Add(TextBox);
}
}
Two other options are:
Implement a LayoutEngine that does the grouping you want.
Implement a composite ToolStripItem that displays a label and text box. You can use the ToolStripRadioButtonMenuItem as an example: https://msdn.microsoft.com/en-us/library/vstudio/ms404318%28v=vs.100%29.aspx

C# Window Form Application, how to efficiently create a dynamic panel on a window form

I would like to create a few panel dynamically in my window form application. Each panel will consist of 3 labels and one text box and one button. Now I know I can hard code this all at once by declaring each variable every time, but it takes a lot of coding and it is obviously not efficient at all.
So my question is: Is there a way to create pre-define panel dynamically where each time a panel is created will have a predefined layout setup already. So all i need to do is to add a panel, its location and size every time, and all the content(like labels, text-box and button) inside the panel are already setup with their location associated with the panel itself. Do I really have to create a class just for that?
Thanks in advance for read and taking your time.
Create Windows Forms control or user control, see http://msdn.microsoft.com/en-us/library/6hws6h2t.aspx
Create a user control, and place on it whatever you like (your labels). Expose public methods/properties of that control so you can control the contents of it. Place as many of those on the form as you like, they will all look and behave same.
Here is an example you can play with...
for (int i = 1; i < 5; i++)
{
var panel1 = new Panel() { Size = new Size(90, 80), Location = new Point(10, i * 100), BorderStyle = BorderStyle.FixedSingle };
panel1.Controls.Add(new Label() { Text = i.ToString(), Location = new Point(10, 20) });
panel1.Controls.Add(new Label() { Text = i.ToString(), Location = new Point(10, 40) });
panel1.Controls.Add(new Label() { Text = i.ToString(), Location = new Point(10, 60) });
Controls.Add(panel1);
}

How do I put a panel of buttons into flow layout panel?

I have a panel of labels, buttons and image that I wish to put into a flow layout panel.
As seen in some tutorial, I understand that it is possible to auto align new and additional buttons into a flow layout panel.
what I would like to ask is that is it possible to put a panel WITHIN a flow layout panel and call multiple instances of the same panel to appear within the flow layout panel.
My panel code would be
this.panelNotification.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.panelNotification.Controls.Add(this.button1);
this.panelNotification.Controls.Add(this.lblImage);
this.panelNotification.Controls.Add(this.lblName);
this.panelNotification.Controls.Add(this.lblLinkName);
this.panelNotification.Controls.Add(this.lblLinkLocation);
this.panelNotification.Controls.Add(this.lblLocation);
this.panelNotification.Location = new System.Drawing.Point(3, 3);
this.panelNotification.Name = "panelNotification";
this.panelNotification.Size = new System.Drawing.Size(506, 100);
this.panelNotification.TabIndex = 17;
So is it possible to include the whole panel into a flow layout panel? if yes, how do i do it. thank you.
Yes, you can put a Panel into a FlowLayoutoutPanel.
No, you can't put a control several times into a FlowLayoutoutPanel (in fact you can, but it is only displayed once).
But what you could do is writing some kind of Factory-Method that creates a new Panel with new Buttons/Labels/other Controls etc. every time you call it, and add these new instances to your FlowLayoutpanel. Something like this:
public class Form1
{
private Panel CreateNotificationPanel()
{
var p = new Panel { BackColor = Color.Red };
p.Controls.Add(new Button { Text = "Test" });
return p;
}
private void Form1_Load(System.Object sender, System.EventArgs e)
{
var flp = new FlowLayoutPanel { Dock = DockStyle.Fill };
flp.Controls.Add(CreateNotificationPanel());
flp.Controls.Add(CreateNotificationPanel());
flp.Controls.Add(CreateNotificationPanel());
this.Controls.Add(flp);
}
public Form1() { Load += Form1_Load; }
}
Another (and problably better) approach would be to create a UserControl that contains your Buttons/Labels/etc. instead of using a panel and adding all controls manually. Just create with the Designer and add new instances of the UserControl to the FlowLayoutPanel.

Categories