如何在循环访问容器时仅检索具有 Name 属性的控件

本文关键字:检索 Name 属性 控件 循环 访问 | 更新日期: 2023-09-27 17:56:16

我目前有一个StackPanel,我正在动态添加控件。(目前是其他堆栈面板、日期选择器、组合框、文本框和标签。 目的是,我正在尝试根据当前选择的报告类型动态生成搜索标准选项。 在这样做时,我正在设置名称,以便以后可以访问它,但是,我遇到了一个问题,我似乎无法在不丢失某些内容或崩溃的情况下获得我想要的所有用户输入控件,因为 StackPanels 没有 Name 属性。

// This one crashes because a child StackPanel doesn't have Name
foreach (var child in this.SearchCriteriaStackPanel.Children)
{
    switch (((Control)child).Name)
    {
        case "startDate":
            this.reports[index].StartDate = ((DatePicker)child).SelectedDate;
            break;
        case "endDate":
            this.reports[index].EndDate = ((DatePicker)child).SelectedDate;
            break;
        case "employeeId":
            this.reports[index].EmployeeId = (int)((ComboBox)child).SelectedValue != 0 ? (int?)((ComboBox)child).SelectedValue : null;
            break;
        case "jobNumber":
            this.reports[index].JobNumber = ((TextBox)child).Text;
            break;
    }
}

.

// This one skips over the DatePickers
foreach (var child in this.SearchCriteriaStackPanel.Children)
{
    switch (((FrameworkElement)child).Name)
    {
        case "startDate":
            this.reports[index].StartDate = ((DatePicker)child).SelectedDate;
            break;
        case "endDate":
            this.reports[index].EndDate = ((DatePicker)child).SelectedDate;
            break;
        case "employeeId":
            this.reports[index].EmployeeId = (int)((ComboBox)child).SelectedValue != 0 ? (int?)((ComboBox)child).SelectedValue : null;
            break;
        case "jobNumber":
            this.reports[index].JobNumber = ((TextBox)child).Text;
            break;
    }
}

我也愿意接受有关如何解决此问题的其他建议。

编辑#1:以下是开始日期选择器的初始化和添加:

var startDateStackPanel = new StackPanel
        {
            Orientation = Orientation.Horizontal,
            Margin = new Thickness(10, 0, 0, 0)
        };
        startDateStackPanel.Children.Add(new Label { Content = "Start Date:" });
        startDateStackPanel.Children.Add(new DatePicker { Width = 120, Name = "startDate" });
this.SearchCriteriaStackPanel.Children.Add(startDateStackPanel);

编辑#2:我可以这样做,但感觉不对...

var list = new List<Control>(this.SearchCriteriaStackPanel.Children.OfType<DatePicker>());
list.AddRange(this.SearchCriteriaStackPanel.Children.OfType<ComboBox>());
list.AddRange(this.SearchCriteriaStackPanel.Children.OfType<TextBox>());
foreach(var child in list)...

如何在循环访问容器时仅检索具有 Name 属性的控件

如果您正在搜索例如 FrameworkElement 的后代,您可以将第一个示例中的 for-each 循环替换为

foreach (var child in this.SearchCriteriaStackPanel.Children.OfType<FrameworkElement>())
{
   ...
}

我解决类似问题的(可能不太理想)方法如下:

foreach (var child in (from Control c in this.SearchCriteriaStackPanel.Children
                       where !(c is StackPanel)
                       select c))
{
    switch (child.Name)
    {
        case "startDate":
            this.reports[index].StartDate = ((DatePicker)child).SelectedDate;
            break;
        case "endDate":
            this.reports[index].EndDate = ((DatePicker)child).SelectedDate;
            break;
        case "employeeId":
            this.reports[index].EmployeeId = (int)((ComboBox)child).SelectedValue != 0 ?(int?)((ComboBox)child).SelectedValue : null;
            break;
        case "jobNumber":
            this.reports[index].JobNumber = ((TextBox)child).Text;
            break;
    }
}

实际上,它跳过所有不属于具有 Name 属性的类型的子项。 您也可以使用if(c is Stackpanel) continue;来执行此操作,但 Linq 始终是我的迭代首选,以防我以后想修改它。后来我包装了相关的类,以消除(从所有到频繁的)switch 语句。