如何通过标识符(Name、Uid...)访问用户控件?
How can I Access user control by identifier (Name,Uid...)?
我有许多(到目前为止有 16 个)我已经构建的用户控件实例。
他们每个人都有相似的属性。我给每一个都起了个名字:
x:Name = "probeX"(其中 X 是一个整数)。
这些控件中的每一个都代表一个电子探针。
我想编写一个方法,通过将 int 值传递到他的属性之一来访问用户控件。
例如:
如果方法签名是:
void SetMeasuredValueToProbe(int probe_number,int 值)
然后路过
SetMeasuredValueToProbe(3, 22);
将 "probe3" 特定 属性 设置为值 22。
我知道我可以在一个方法中制作长的 switch case。
但将来我想以指数方式增加探针的数量。
所以我想知道命名和访问用户控件数组的正确方法是什么。
XAML:
<StackPanel
Grid.Column="0">
<uc:ProbeTestControl x:Name="probe1" x:Uid="1" ProbeValue ="1"/>
<uc:ProbeTestControl x:Name="probe2" ProbeValue ="2"/>
<uc:ProbeTestControl x:Name="probe3" ProbeValue ="3"/>
<uc:ProbeTestControl x:Name="probe4" ProbeValue ="4"/>
<uc:ProbeTestControl x:Name="probe5" ProbeValue ="5"/>
<uc:ProbeTestControl x:Name="probe6" ProbeValue ="6"/>
<uc:ProbeTestControl x:Name="probe7" ProbeValue ="7"/>
<uc:ProbeTestControl x:Name="probe8" ProbeValue ="8"/>
</StackPanel>
<StackPanel
Grid.Column="1">
<uc:ProbeTestControl x:Name="probe9" ProbeValue ="9"/>
<uc:ProbeTestControl x:Name="probe10" ProbeValue ="10"/>
<uc:ProbeTestControl x:Name="probe11" ProbeValue ="11"/>
<uc:ProbeTestControl x:Name="probe12" ProbeValue ="12"/>
<uc:ProbeTestControl x:Name="probe13" ProbeValue ="13"/>
<uc:ProbeTestControl x:Name="probe14" ProbeValue ="14"/>
<uc:ProbeTestControl x:Name="probe15" ProbeValue ="15"/>
<uc:ProbeTestControl x:Name="probe16" ProbeValue ="16"/>
</StackPanel>
主窗口中的方法 Class:
private void SetMeasuredValueToProbe(int probe_number, int value )
{
switch (probe_number)
{
case 1:
probe1.MeasuredValueBox = value;
break;
case 2:
probe2.MeasuredValueBox = value;
break;
default:
break;
}
}
我想知道这样做的优雅方式,无需制作意大利面条代码。
一种方法是给根x:Name
Grid
:
<Grid x:Name="LayoutRoot">
...
</Grid>
然后在您的代码中,您可以按名称找到探测用户控件。像这样:
var probe = LayoutRoot.GetChildByName<ProbeTestControl>($"probe{probe_number}");
这是我使用的扩展方法:
public static T GetChildByName<T>(this FrameworkElement element, string name)
where T : FrameworkElement
{
if (element == null) return null;
return (T)element.FindName(name) ?? element.GetChildrenOfType<T>().FirstOrDefault(c => c.Name == name);
}
public static IEnumerable<T> GetChildrenOfType<T>(this DependencyObject element)
where T : DependencyObject
{
return element.GetChildrenRecursive().OfType<T>();
}
private static IEnumerable<DependencyObject> GetChildrenRecursive(this DependencyObject element)
{
if (element == null)
{
throw new ArgumentNullException(nameof(element));
}
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
{
var child = VisualTreeHelper.GetChild(element, i);
yield return child;
foreach (var item in child.GetChildrenRecursive())
{
yield return item;
}
}
}
只要所有探测器都存在于同一个 XAML 树中,一切都应该有效。
希望对您有所帮助。
我有许多(到目前为止有 16 个)我已经构建的用户控件实例。 他们每个人都有相似的属性。我给每一个都起了个名字: x:Name = "probeX"(其中 X 是一个整数)。 这些控件中的每一个都代表一个电子探针。
我想编写一个方法,通过将 int 值传递到他的属性之一来访问用户控件。
例如: 如果方法签名是: void SetMeasuredValueToProbe(int probe_number,int 值) 然后路过 SetMeasuredValueToProbe(3, 22);
将 "probe3" 特定 属性 设置为值 22。
我知道我可以在一个方法中制作长的 switch case。 但将来我想以指数方式增加探针的数量。 所以我想知道命名和访问用户控件数组的正确方法是什么。
XAML:
<StackPanel
Grid.Column="0">
<uc:ProbeTestControl x:Name="probe1" x:Uid="1" ProbeValue ="1"/>
<uc:ProbeTestControl x:Name="probe2" ProbeValue ="2"/>
<uc:ProbeTestControl x:Name="probe3" ProbeValue ="3"/>
<uc:ProbeTestControl x:Name="probe4" ProbeValue ="4"/>
<uc:ProbeTestControl x:Name="probe5" ProbeValue ="5"/>
<uc:ProbeTestControl x:Name="probe6" ProbeValue ="6"/>
<uc:ProbeTestControl x:Name="probe7" ProbeValue ="7"/>
<uc:ProbeTestControl x:Name="probe8" ProbeValue ="8"/>
</StackPanel>
<StackPanel
Grid.Column="1">
<uc:ProbeTestControl x:Name="probe9" ProbeValue ="9"/>
<uc:ProbeTestControl x:Name="probe10" ProbeValue ="10"/>
<uc:ProbeTestControl x:Name="probe11" ProbeValue ="11"/>
<uc:ProbeTestControl x:Name="probe12" ProbeValue ="12"/>
<uc:ProbeTestControl x:Name="probe13" ProbeValue ="13"/>
<uc:ProbeTestControl x:Name="probe14" ProbeValue ="14"/>
<uc:ProbeTestControl x:Name="probe15" ProbeValue ="15"/>
<uc:ProbeTestControl x:Name="probe16" ProbeValue ="16"/>
</StackPanel>
主窗口中的方法 Class:
private void SetMeasuredValueToProbe(int probe_number, int value )
{
switch (probe_number)
{
case 1:
probe1.MeasuredValueBox = value;
break;
case 2:
probe2.MeasuredValueBox = value;
break;
default:
break;
}
}
我想知道这样做的优雅方式,无需制作意大利面条代码。
一种方法是给根x:Name
Grid
:
<Grid x:Name="LayoutRoot">
...
</Grid>
然后在您的代码中,您可以按名称找到探测用户控件。像这样:
var probe = LayoutRoot.GetChildByName<ProbeTestControl>($"probe{probe_number}");
这是我使用的扩展方法:
public static T GetChildByName<T>(this FrameworkElement element, string name)
where T : FrameworkElement
{
if (element == null) return null;
return (T)element.FindName(name) ?? element.GetChildrenOfType<T>().FirstOrDefault(c => c.Name == name);
}
public static IEnumerable<T> GetChildrenOfType<T>(this DependencyObject element)
where T : DependencyObject
{
return element.GetChildrenRecursive().OfType<T>();
}
private static IEnumerable<DependencyObject> GetChildrenRecursive(this DependencyObject element)
{
if (element == null)
{
throw new ArgumentNullException(nameof(element));
}
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
{
var child = VisualTreeHelper.GetChild(element, i);
yield return child;
foreach (var item in child.GetChildrenRecursive())
{
yield return item;
}
}
}
只要所有探测器都存在于同一个 XAML 树中,一切都应该有效。
希望对您有所帮助。