选择组中的下一个单选按钮

本文关键字:下一个 单选按钮 选择 | 更新日期: 2023-09-27 17:53:20

是否有一种标准的方式以编程方式选择/检查一组单选按钮中的下一个单选按钮?我正在寻找的行为类似于在容器中分组的单选按钮的默认箭头键按下事件:当我按下箭头键时,自动选择并检查下一个(或上一个)单选按钮。

选择组中的下一个单选按钮

我是这样做的:

    var rads = panel1.Controls.OfType<RadioButton>(); // Get all radioButtons of desired panel
    rads.OrderBy(r => r.Top); // sort them. Please specify what you mean "next" here. I assume that you need next one at the bottom
    // find first checked and set checked for next one
    for (int i = 0; i < rads.Count()-1; i++) 
    {
        if (rads.ElementAt(i).Checked)
        {
            rads.ElementAt(i + 1).Checked = true; 
            return;
        }
    }

每个集装箱只能检查一个RadioButton。这就是单选按钮的意义所在。如果您想使用CheckBox,您可以使用以下代码:

foreach (CheckBox control in Controls.OfType<CheckBox>())
{
    control.Checked = true;
}

如果您希望按顺序检查控件,您可以执行

new Thread(() =>
{
    foreach (CheckBox control in Controls.OfType<CheckBox>())
    {
        control.BeginInvoke((MethodInvoker) (() => control.Checked = true));
        Thread.Sleep(500);
    }
}).Start();

另一次阅读你的原始帖子,我很难理解你的意思。你能详细说明一下,以便我更新我的回复吗?

最快的解决方案:(如果您的应用程序有焦点…)

//assuming you are at the first radio button
SendKeys({DOWN});

更困难的解决方案:http://msdn.microsoft.com/en-us/library/system.windows.automation.automationelement.findall.aspx

//Write method to get window element for the window you wish to manipulate
//Open an instance of notepad and the WindowTitle is: "Untitled - Notepad"
//you could use other means of getting to the Window element ...
AutomationElement windowElement = getWindowElement("Untitled - Notepad");
//Use System.Windows.Automation to find all radio buttons in the WindowElement
//pass the window element into this method
//This method will return all of the radio buttons in the element that is passed in
//however, if you have a Pane inside of the WIndow and then, the buttons are contained
//in the pane, you will have to get to the pane and then pass the pane into the findradiobuttons method
AutomationElementCollection radioButtons = FindRadioButtons(windowElement);
//could iterate through the radioButtons to determine which is selected...
//then select the next index etc.    
//then programmatically select the radio button
//pass the selected radioButton AutomationElement into a method that Invokes the Click etc.
clickButtonUsingUIAutomation(radioButtons[0]);
/// <summary> 
/// Finds all enabled buttons in the specified window element. 
/// </summary> 
/// <param name="elementWindowElement">An application or dialog window.</param>
/// <returns>A collection of elements that meet the conditions.</returns>
AutomationElementCollection FindRadioButtons(AutomationElement elementWindowElement)
{
    if (elementWindowElement == null)
    {
        throw new ArgumentException();
    }
    Condition conditions = new AndCondition(
      new PropertyCondition(AutomationElement.IsEnabledProperty, true),
      new PropertyCondition(AutomationElement.ControlTypeProperty, 
          ControlType.RadioButton)
      );
    // Find all children that match the specified conditions.
    AutomationElementCollection elementCollection = 
    elementWindowElement.FindAll(TreeScope.Children, conditions);
    return elementCollection;
}
    private AutomationElement getWindowElement(string windowTitle)
    {
        AutomationElement root = AutomationElement.RootElement;
        AutomationElement result = null;
        foreach (AutomationElement window in root.FindAll(TreeScope.Children, new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window)))
        {
            try
            {
                if (window.Current.Name.Contains(windowTitle) && window.Current.IsKeyboardFocusable)
                {
                    result = window;
                    break;
                }
            }
            catch (Exception e)
            {
                throw;
            }
        }
        return result;
    }
    private void ClickButtonUsingUIAutomation(AutomationElement control)
    {
        // Test for the control patterns of interest for this sample. 
        object objPattern;
        ExpandCollapsePattern expcolPattern;
        if (true == control.TryGetCurrentPattern(ExpandCollapsePattern.Pattern, out objPattern))
        {
            expcolPattern = objPattern as ExpandCollapsePattern;
            if (expcolPattern.Current.ExpandCollapseState != ExpandCollapseState.LeafNode)
            {
                Button expcolButton = new Button();
                //expcolButton.Margin = new Thickness(0, 0, 0, 5);
                expcolButton.Height = 20;
                expcolButton.Width = 100;
                //expcolButton.Content = "ExpandCollapse";
                expcolButton.Tag = expcolPattern;
                expcolPattern.Expand();
                //SelectListItem(control, "ProcessMethods");
                //expcolButton.Click += new RoutedEventHandler(ExpandCollapse_Click);
                //clientTreeViews[treeviewIndex].Children.Add(expcolButton);
            }
        }
        TogglePattern togPattern;
        if (true == control.TryGetCurrentPattern(TogglePattern.Pattern, out objPattern))
        {
            togPattern = objPattern as TogglePattern;
            Button togButton = new Button();
            //togButton.Margin = new Thickness(0, 0, 0, 5);
            togButton.Height = 20;
            togButton.Width = 100;
            //togButton.Content = "Toggle";
            togButton.Tag = togPattern;
            togPattern.Toggle();
            //togButton.Click += new RoutedEventHandler(Toggle_Click);
            //clientTreeViews[treeviewIndex].Children.Add(togButton);
        }
        InvokePattern invPattern;
        if (true == control.TryGetCurrentPattern(InvokePattern.Pattern, out objPattern))
        {
            invPattern = objPattern as InvokePattern;
            Button invButton = new Button();
            //invButton.Margin = new Thickness(0);
            invButton.Height = 20;
            invButton.Width = 100;
            //invButton.Content = "Invoke";
            invButton.Tag = invPattern;
            //invButton.Click += new EventHandler(Invoke_Click);
            invPattern.Invoke();
            //clientTreeViews[treeviewIndex].Children.Add(invButton);
        }
    }

所以,似乎没有标准的方法来处理这个问题。我最终从Andrey的解决方案中获得灵感,并编写了一个扩展方法,可以从一组RadioButton中的任何特定RadioButton中调用。

public static void CheckNextInGroup(this RadioButton radioButton, bool forward) {
    var parent = radioButton.Parent;
    var radioButtons = parent.Controls.OfType<RadioButton>();  //get all RadioButtons in the relevant container
    var ordered = radioButtons.OrderBy(i => i.TabIndex).ThenBy(i => parent.Controls.GetChildIndex(i)).ToList();  //Sort them like Windows does
    var indexChecked = ordered.IndexOf(radioButtons.Single(i => i.Checked)); //Find the index of the one currently checked
    var indexDesired = (indexChecked + (forward ? 1 : -1)) % ordered.Count;  //This allows you to step forward and loop back to the first RadioButton
    if (indexDesired < 0) indexDesired += ordered.Count;  //Allows you to step backwards to loop to the last RadioButton
    ordered[indexDesired].Checked = true;
}

然后,从任何可以访问您的特定RadioButton的地方,您可以使其集合中的下一个或前一个RadioButton得到检查。这样的:

radioButton1.CheckNextInGroup(true); //Checks the next one in the collection
radioButton1.CheckNextInGroup(false); //Checks the previous one in the collection