How to tab through RadioButton group in Windows Forms without selecting - winforms

I have a Windows Forms GUI that has a bunch of controls, one of which is a FlowLayoutPanel containing a group of RadioButtons.
I can tab to the first RadioButton (TabIndex and TabStop set properly), but when I hit tab again it takes me to the next control on the form, not the next radio button in the FlowLayoutPanel.
Once the first RadioButton has focus, the only way to go through the group is to use up/down arrows, but that actually selects the RadioButton. Selecting a RadioButton kicks off some other stuff, so I just want a way to tab through the list to figure out what to select.
What I want, ideally, is to have each RadioButton act like any other control on the page and allow me to tab through the whole group without selecting a RadioButton until I hit Space.

This tab order is default Windows behaviour and it is rarely good practice to change this.
It happens as the Radio Buttons in a group have TabStop juggled to work this way.
To change this, explicitly set the Tab Stop to true every time it is reset:
public Form1()
{
InitializeComponent();
foreach (var control in this.flowLayoutPanel1.Controls.OfType<RadioButton>())
{
control.GotFocus += (s,a) => SetTabStops(flowLayoutPanel1);
control.CheckedChanged+= (s,a) => SetTabStops(flowLayoutPanel1);
}
}
private static void SetTabStops(Control host)
{
foreach (Control control in host.Controls)
{
control.TabStop = true;
}
}

Related

How to change content in the same form

I need to view new content in the same form (not to open a new form) when I click some button.
For exapmle this opera installer. When I click "Options" content changes in this window. And when I click "Back" I see previous components.
There is different ways to achive this easily :
You can use the TabControl control, which holds different pages you can design separatly in the vs designer.
Then you choose the initial one, hide the tabs selection bar on top, and control the TabPage selection with your buttons with SelectedTab or SelectedIndex properties.
Or you can simply wrap each section in a GroupBox control, set them all to Visible=false except the initial one and handle their visibility with your buttons with something like :
List<GroupBox> sections = new List<GroupBox>() { /* add your sections */ };
nextButton.OnClick += (o, e) =>
{
sections.ForEach(s => s.Visible = .../* condition to select the section you want displayed and hide others */);
};

Implementation of menu buttons in WPF/MVVM/Prism

I have a Region in the top left of the WPF application which I want to be my global button bar where the user chooses which screen they want to view, and the appropriate content will then be displayed in the main region. THere will also be a sub navigation region in the top right with sub-menu options within that screen, eg if the user clicked "Maintenance" from the main menu, the sub menu would show options for New, Update, Delete, Edit etc.
What I want to have is a way to create a custom menu bar by simply specifying a list of Text button names, and ICommand/Parameter pairs for the action to invoke on button click. The natural way to do this would be have a MenuButtonViewModel class with dependency properties Title, Command and CommandParameter. One more would also be needed, IsSelected, so there is some visual way for the user to see which screen you are currently on, so it needs to behave like a toggle button, but where only one button in the group can be selected at a time. I can then have a UserControl where the content of the bar binds to an ObservableCollection and uses data templates to render the button bar.
I have tried a few ways of doing this so far but cannot figure out a way that gives me the visual behaviour I want. These are my requirements
1) Button to change background to a different Brush OnMouseOver
2) When button is selected, a different Brush is displayed as the background until a new button in the group is selected, like a togglebutton IsSelected behaviour
3) Only one button in the group can be selected at a time
The ways I have tried to do this so far are
1) Extending RadioButton with my own class, adding dependency properties for command and commandparameter. Setting all controls to have the same group Id. Data template to override display of radio button to make it look like a visual button with triggers for mouseover and isselected.
This works fine, except for one thing. Once you select a radio button in a group, there is no way to deselect all options in the radio button group. So if you navigate to "maintenance" and then click the sub menu for "Countries" for example, then you are displayed the country maintenance screen. If you then go to a different area of the app and select "Deal Entry" from the main menu, you are taken to the deal entry screen. If you then click "Maintenance", it displays the generic "maintenance" content and brings back the sub menu control for maintenance, where "Country" is selected in the radio button group, but this is undesirable. When you navigate back to Maintenance, it should deselect all sub menu options, display the generic maintenance landing page content and let you select a sub menu option before displaying that screens content. The first time you load Maintenance, nothing is selected, but once you have chosen an option, then there is no way to have nothing selected again when you reload the maintenance screen.
2) I then tried extending a ListBox, styling it with a horizontal stackpanel for the content, each listboxitem is a menubuttonViewModel. This allows me to only select a single option at a time and to clear the selection when you navigate away from the page. It also lets me change the background when you mouse over each listboxitem.
The bit I can't get working with the listbox is to have the background different on the IsSelected trigger. There seems to be some trigger on the default ListBoxItem template that overrides anything you specify in CSS so no matter what trigger I put on the listboxitem or menubuttonviewmodel style, the background simply does not change. I think I need to redefine the data and content template for listboxitem, but only have it apply for this listbox, so it can't be a global template change to all listboxitems - as I want to be able to use listboxes elsewhere in the app without inheriting this behaviour.
Can anyone give their thoughts on these two approaches and how to perhaps solve the issues I'm having to make one of them work in the way I want, particularly if you can advise how I can override the content/data template for the listboxitems in my style so they do not use the default triggers, and I can get the IsSelected trigger working for me?
If I understood correctly, you would want to clear the selection on the RadioButtons from the Sub-Menu each time you navigate back from another Main Menu option.
In order to solve this, you could have every Radio Button "unchecked" by manually setting the RadioButton´s IsChecked property value to false. A possible solution could be the following:
If you want to clear any checked option from the Sub-Menu everytime you navigate to a different section of the Main Menu, you could first notify to the Sub-Menu´s ViewModel by publishing an event using the EventAggregator after selecting and clicking a different MainMenu button, from the SelectionChangedEventHandler method of the Main Menu´s ViewModel.
Therefore, the Sub-Menu EventHandler of the published event would update each RadioButton´s IsChecked property value to false, which it could be accomplished by using a "Two-Way" Binding between each IsChecked property defined on the View, and each boolean "RadioButton1IsChecked" property implemented on the ViewModel.
I hope this helped you.

How to add already existing ToolStrip Buttons to a ToolStrip Dynamically

I have a Winform Applicaion useing an MDI Form. On the MDI Form I have a ToolStrip with buttons (Buttons have images) on it acting as the main menu buttons for the application. So when user clicks on a button on the toolstrip the mdichild form for that button opens the child form.
So I have six buttons with images already created and in the project. But I want the user to select the buttons they want to appear on the toolstrip.
So the user opens the application and there is only one button on the toolstrip. The user clicks on that button and a child screen opens showing all the available existing buttons that could be on the toolstrip. The user selects the buttons they want to appear on the toolstrip then clicks that save button on the child screen.
What I want is that as soon as the user clicks that save button the buttons that the user selected should automatically appear on the toolstrip.
Right now I have to have the user close the applicaiton then reopen it for the buttons they selected to appear on the toolstrip.
How so I get the buttons to appear automatically?
Just create all of the ToolStripButtons, and set each one's Visible property to false. When the user picks them to be shown, change the Visible property of the ToolStripButton to true. They'll automatically appear on the ToolStrip.
I tested using VS2010 with Oxygene from RemObjects (formerly AKA Delphi Prism).
Start a new WinForms application
Drop a ToolStrip on the window. Right-click it and choose Insert standard items.
Double-click the New button (newToolStripButton, the one on the left end), and add the following code to the newToolStripButton_Click handler:
// Oxygene version: helpToolStripButton.Visible := not helpToolStripButton.Visible;
helpToolStripButton.Visible != helpToolStripButton.Visible;
Run the application, and click the newTooStripButton repeatedly, and watch the right-most ToolStripButton (the Help button) appear and disappear from the ToolStrip.
You can create any ToolStrip and add it to a MenuStrip.DropDownItems.Add.
The click EventHandler must be a (s,e) function.
ToolStripMenuItem ts = new ToolStripMenuItem();
ts.Name = $"MyMenuStrip";
ts.Text = "New MenuStrip";
ts.Click += new EventHandler(this.ToolStripMenuItem_Click);
private void ToolStripMenuItem_Click(object sender, EventArgs e)
{
ToolStripMenuItem clickedMenuItem = sender as ToolStripMenuItem;
Trace.WriteLine($"Clicked: {clickedMenuItem.Text}");
}

Control.Leave Triggered by MouseDown, not MouseUp

I have a C# .NET WinForm. In the form, I allow a user to add an item to a ListView by double-clicking in the ListView. This adds a TextBox control to the ListView and places the key cursor in the TextBox so a user can type.
I detect that a user is done with an item in a couple of ways (e.g. pressing Enter, Esc, Tab...), but also when they Leave (TextBox.Leave) the TextBox.
The problem is this set of steps:
User triggers TextBox.Leave by mousing down outside of the TextBox.
I add the new item to the ListView.
I select the the new item in the ListView.
Mouse up occurs and the new item that I just selected, loses focus and is unselected.
What I would like is for TextBox.Leave to be triggered by MouseUp, not MouseDown. How can I accomplish this?
Edit: Cody suggests using the ListView.LabelEdit property. Here are my results trying that:
listView_DoubleClick(...) {
listView.LabelEdit = true;
if(double clicked on existing listViewItem) {
listViewItem.BeginEdit(); //this works as expected
} else {
var newItem = listView.Items.Add("");
newItem.BeginEdit(); //this doesn't work, see below
}
}
The call to newItem.BeginEdit() only works when the user double clicks where the new item will show up. If they double click on any other blank area in the listview the new item is added, but it does not enter edit mode. What's going on here?
Pressing the mouse down on another control is causing that other control to request the focus and so the focus moving causes the TextBox.Leave event to occur. Preventing ever other possible control from requesting the focus is not a very viable option. But luckly you only need to prevent the ListView from using the MouseDown to shift focus. So you need to override the WndProc of your ListView and when the MouseDown windows message occurs and you are currently showing a TextBox you eat the message. In order words you do not allow the base class to process it.

UI Design Concepts in WinForms

In one certain case I want to disable the tabpannel so that the controlls in the tab panel are disabled.
I want to disable the tab pannel but still I want ennable the controls in tab pannel.the need is User cannot switch over to the annother tabpannel in a certain senerio.
How can I do this requirement?.
by
dinesh
Use something besides a tab panel.
It is not standard behavior for a tab panel to have one tab "stuck" so that the user cannot move to the other tabs. You're going to throw users off if you do this.
What you are after sounds like a modal dialog. It sounds like you don't want the users to move away from a certain screen until they're doing entering some data or some such. The modal dialog is built for this purpose.
There is no direct way to disable Tab Page, only you can remove it. But in your case, you can't remove the Tab, So I think you need to put some code in the Tab_SelectionIndex change event. And when ever the Tab index comes, set it back to another one.
Try this code
private void tabControl1_SelectedIndexChanged(object sender, EventArgs e)
{
if (tabControl1.SelectedIndex == 1)
{
tabControl1.SelectedIndex = -1;
}
}
In addition to anuraj's answer, set the colour of the tab text to the disabled text colour state, so it is a visual cue it is "disabled".

Resources