在迭代容器时,如何仅检索具有Name属性的控件?

时间:2013-01-28 16:18:50

标签: c# .net wpf

我目前有一个StackPanel,我正在动态添加控件。 (目前其他堆栈面板,DatePickers,ComboBoxes,TextBoxes和Labels。)意图是,我试图根据当前选择的报告类型动态生成搜索critera选项。在这样做我设置名称,以便我可以稍后访问它,但是,我遇到一个问题,我似乎无法获得我想要的所有用户输入控件,没有丢失的东西或崩溃,因为StackPanels不' t有一个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: 这是startDate DatePicker的初始化和添加:

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)...

2 个答案:

答案 0 :(得分:3)

如果您正在搜索来自例如您可以使用

替换第一个示例中的for-each循环的FrameworkElement
foreach (var child in this.SearchCriteriaStackPanel.Children.OfType<FrameworkElement>())
{
   ...
}

答案 1 :(得分:1)

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

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语句。