2

So you know how in c# using normal forms you can loop through a panel and get all the labels inside of it? So you can do something like this:

foreach(Label label in Panel.Controls)

is there a way of doing this for grids? something like

foreach(Lable lable in Grid)

so this foreach could be inside a function that passes a grid object like so

private void getLabels(Grid myGrid)
{
  foreach(Label label in myGrid)
}

if i do this, it tells me "error CS1579: foreach statement cannot operate on variables of type 'System.Windows.Controls.Grid' because 'System.Windows.Controls.Grid' does not contain a public definition for 'GetEnumerator'"

is there another way of doing this that i am now aware of?

Any help would be appreciated.

Doctor06
  • 677
  • 1
  • 13
  • 28

3 Answers3

4

normal forms - WPF us the normal way of doing .Net Windows UIs in 2014.

If you're working with WPF, you need to leave behind any and all notions you got from ancient technologies and understand and embrace The WPF Mentality.

Basically, you don't "iterate" over anything in WPF because there's absolutely no need to do so.

The UI's responsibility is to show data, not to store it nor manipulate it. Therefore whatever data you need to show must be stored in a proper Data Model or ViewModel and the UI must use proper DataBinding to access that, rather than procedural code.

So, for example, say you have a Person class:

public class Person
{
    public string LastName {get;set;}

    public string FirstName {get;set;}
}

You will want to set the UI's DataContext to a list of that:

//Window constructor:
public MainWindow()
{
    //This is required.
    InitializeComponent();

    //Create a list of person
    var list = new List<Person>();

    //... Populate the list with data.

    //Here you set the DataContext.
    this.DataContext = list;
}

Then you will want to show that in a ListBox or another ItemsControl-based UI:

<Window ...>
    <ListBox ItemsSource="{Binding}">

    </ListBox>
</Window>

And then you'll want to use WPF's Data Templating capabilities to define how to show each instance of the Person class in the UI:

<Window ...>
   <Window.Resources>
      <DataTemplate x:Key="PersonTemplate">
          <StackPanel>
              <TextBlock Text="{Binding FirstName}"/>
              <TextBlock Text="{Binding LastName"/>
          </StackPanel>
      </DataTemplate>
   </Window.Resources>

   <ListBox ItemsSource="{Binding}"
            ItemTemplate="{StaticResource PersonTemplate}"/>
</Window>

Finally, if you need to change the Data at runtime, and have those changes reflected (shown) in the UI, your DataContext classes must Implement INotifyPropertyChanged:

public class Person: INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string name)
    {
        var handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(name));
    }

    private string _lastName;
    public string LastName
    {
        get { return _lastName; }
        set
        {
            _lastName = value;
            OnPropertyChanged("LastName");
        }
    }

    private string _firstName;
    public string FirstName
    {
        get { return _firstName; }
        set
        {
            _firstName = value;
            OnPropertyChanged("FirstName");
        }
    }
}

Finally you iterate over the List<Person> and change the data items' properties rather than manipulating the UI:

foreach (var person in list)
    person.LastName = "Something";

While leaving the UI alone.

Community
  • 1
  • 1
Federico Berasategui
  • 43,562
  • 11
  • 100
  • 154
2

Iterate through Grid.Children and cast everything to Label. If it's not null, you have found a Label.

djdanlib
  • 21,449
  • 1
  • 20
  • 29
0

You can do like this:

foreach (UIElement el in grid.Children)
{
    if (el.GetType() == typeof(Label))
    {
        Label lbl = (Label)el;
        lbl.Foreground = new SolidColorBrush(Colors.Red);
    }
}