Home > Back-end >  What is the proper way of finding a control(label) in a grid under row definitions using FindName?
What is the proper way of finding a control(label) in a grid under row definitions using FindName?

Time:04-20

I have this piece of code (that doesn't work) that accepts a grid list of type grid and a label list of type label. This attempts to find if the label exists and then change its properties.

Error: NullReferenceException

try
{
    var label = (Label)gridlist[i].FindName(labellist[i].Name);
    label.Content = (ipaccuracy[i, 0] == true ? @"ⓘ " : "")   toreturn;
    label.ToolTip = string.Join(Environment.NewLine, tooltip);
}
    catch (Exception ex)
{
    Debug.WriteLine(ex);
}

This piece of code is run through a Task.Run() and is part of a dynamic UI. When the UI changes, the parameters that are run to this code (gridlist and labellist) changes BUT I want it to error out instead of changing the wrong part of the UI.

My current workaround for this is:

labellist[i].Content = (ipaccuracy[i, 0] == true ? @"ⓘ " : "")   toreturn;
labellist[i].ToolTip = string.Join(Environment.NewLine, tooltip);

But this allows the UI to give incorrect information for a few seconds before the Task.Run() gets called to renew with the correct information per row. (When the UI changes, the default text is "Loading" while waiting for the info to load in)

Here is the code of how I create the relevant UI:

RowDefinition newrow2 = new RowDefinition();
newrow2.Name = "column2_"   gamename.CleanName()   ip.CleanName();

Debug.WriteLine(newrow2.Name);
newrow2.Height = new GridLength(28);
rows2.Add(newrow2);
game_details_right.RowDefinitions.Add(newrow2);

var g2 = new Grid { Name = "column2_"   gamename.CleanName()   ip.CleanName()   "_grid", };

active_gridlist.Add(g2);

var l2 = new Label
         {
           Name = "column2_"   gamename.CleanName()   ip.CleanName()   "_text",
           Content = "Loading",
         };

Debug.WriteLine("column2_"   gamename.CleanName()   ip.CleanName()   "_text");

listlabelsping.Add(l2);

g2.Children.Add(l2);
game_details_right.Children.Add(g2);
Grid.SetRow(g2, s   1);

s  ;

Task.Run(() =>
          {

           UpdatePingRead(active_iplist, active_ipaccuracy, listlabelsping, active_gridlist.ToArray());

          });

From what I Intended with the code, here is the hierarchy of the controls.

<Grid Name="game_details_right">
   <Grid.RowDefinitions>
      <RowDefinition Name="column2_game_19216800" Height="*"/>
      ...
   <Grid.RowDefinitions/>

   <Grid Grid.Row="0" Name="column2_game_19216800_grid">
      <Label Name="column2_game_19216800_text" Content="thing"/>
   </Grid>
   ...
</Grid>

What am I doing wrong with FindName? I have confirmed that I am using the right name, by instead of using a labellist, I passed the same parameters from the constructor to the Task.

Code explanation: I have a list of IP Addresses that I ping every X seconds. The list changes depending on what the user wants to see. It is wasteful to ping servers that results wont be given to the user. The list is updated every time the user changes their choice in a combobox. The pinger is run inside a Task.Run() so it doesn't hog up the UI while it waits for the server's feedback. This has the added benefit of ensuring that a ping is always attempted at the set interval and keeps any mathematical equations that have time delta relatively accurate.

Link for Buggy Code. Link for Fixed (and cleaner) Code.

CodePudding user response:

The main problem here is FindName() only searches registered names of controls. XAML hardcoded controls should have this automatically set (if you name them). However, programmatically created controls need to be registered using RegisterName(name, object).

I added this at the end of the constructor then ignored the NullReferenceException breakpoint.

RegisterName(l2.Name,l2);
RegisterName(g2.Name,g2);
RegisterName(newrow2.Name,newrow2);

This fixed my problem.

  • Related