使用 FindName 在行定义下的网格中查找控件(标签)的正确方法是什么?

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

我有这段代码(不起作用)接受网格类型的网格列表和标签类型的标签列表。这会尝试查找标签是否存在,然后更改其属性。

错误: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);
}

这段代码是 运行 通过 Task.Run() 并且是动态 UI 的一部分。当 UI 更改时,运行 此代码(网格列表和标签列表)的参数更改但我希望它出错而不是更改 UI.[=16 的错误部分=]

我目前的解决方法是:

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

但这允许 UI 在调用 Task.Run() 以每行更新正确信息之前的几秒钟内提供不正确的信息。 (当 UI 更改时,默认文本为“正在加载”,同时等待信息加载)

这是我如何创建相关的代码 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());

          });

根据我对代码的意图,这里是控件的层次结构。

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

我在使用 FindName 时做错了什么?我已经确认我使用了正确的名称,而不是使用标签列表,我将相同的参数从构造函数传递给任务。

代码解释: 我有一个 IP 地址列表,我每 X 秒 ping 一次。该列表根据用户希望看到的内容而变化。不向用户提供结果的 ping 服务器是一种浪费。每次用户在组合框中更改他们的选择时,列表都会更新。 pinger 在 Task.Run() 中 运行,因此它在等待服务器反馈时不会占用 UI。这样做的额外好处是确保始终在设定的时间间隔内尝试执行 ping,并使任何具有时间增量的数学方程式保持相对准确。

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

这里的主要问题是 FindName() 只搜索控件的注册名称。 XAML 硬编码控件应该自动设置(如果你给它们命名)。但是,需要使用 RegisterName(name, object).

注册以编程方式创建的控件

我在构造函数的末尾添加了它,然后忽略了 NullReferenceException 断点。

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

这解决了我的问题。