C# 为WPF ControlTemplate子级指定唯一名称
在我们的WPF软件中,我们使用了一个C# 为WPF ControlTemplate子级指定唯一名称,c#,wpf,C#,Wpf,在我们的WPF软件中,我们使用了一个ControlTemplate,它定义了一个ToggleButton,使窗口收缩/扩展。ToggleButton的定义如下: 我们正在创建一个自定义的DockPanel,它在右上角包含此按钮。我们的应用程序最多可以同时包含三个DockPanels: 上图显示了每个DockPanel右侧的小矩形 请注意,从定义中可以看出,所有三个矩形都有相同的名称:“PART\u MaximizeToggle”。这会在编写CodedUI程序以自动化测试时造成麻烦。Code
ControlTemplate
,它定义了一个ToggleButton
,使窗口收缩/扩展。ToggleButton
的定义如下:
我们正在创建一个自定义的DockPanel
,它在右上角包含此按钮。我们的应用程序最多可以同时包含三个DockPanel
s:
上图显示了每个DockPanel
右侧的小矩形
请注意,从定义中可以看出,所有三个矩形都有相同的名称:“PART\u MaximizeToggle”
。这会在编写CodedUI程序以自动化测试时造成麻烦。CodedUI将他们所有的好友姓名捕获为“PART\u maximitedoggle”
,名称字段为空。DockPanel
s的位置和顺序可以根据用户的需要而改变
我们如何让CodedUI捕捉到预期点击的准确按钮?我正在考虑使每个切换按钮的名称
动态化,但针对特定的DockPanel
进行固定
我该怎么做?有更好的方法吗?您可以通过为每个前缀增加一个计数器来自动分配()名称。
(这只是概念证明,还应检查名称是否有效)
公共静态类测试属性
{
私有静态只读字典_计数器=新字典();
公共静态只读DependencyProperty AutoNameProperty=DependencyProperty.RegisterAttached(
“AutoName”、typeof(string)、typeof(TestingProperties)、新PropertyMetadata(默认值(string)、OnAutoNamePropertyChanged));
AutoNamePropertyChanged上的私有静态无效(DependencyObject元素,DependencyPropertyChangedEventArgs)
{
字符串值=(字符串)eventArgs.NewValue;
if(String.IsNullOrWhiteSpace(value))返回;
if(DesignerProperties.GetIsInDesignMode(元素))返回;
如果(!(元素为FrameworkElement))返回;
int指数=0;
如果(!\u计数器容器(值))
_计数器。添加(值、索引);
其他的
索引=++计数器[值];
string name=string.Format(“{0}{1}”,值,索引);
((FrameworkElement)元素)。名称=名称;
((FrameworkElement)元素).RegisterName(名称,元素);
}
公共静态void SetAutoName(DependencyObject元素,字符串值)
{
SetValue(AutoNameProperty,value);
}
公共静态字符串GetAutoName(DependencyObject元素)
{
返回(字符串)元素.GetValue(AutoNameProperty);
}
}
XAML中的用法:
生成的可视化树:
您可以通过为每个前缀增加一个计数器来自动分配()名称。
(这只是概念证明,还应检查名称是否有效)
公共静态类测试属性
{
私有静态只读字典_计数器=新字典();
公共静态只读DependencyProperty AutoNameProperty=DependencyProperty.RegisterAttached(
“AutoName”、typeof(string)、typeof(TestingProperties)、新PropertyMetadata(默认值(string)、OnAutoNamePropertyChanged));
AutoNamePropertyChanged上的私有静态无效(DependencyObject元素,DependencyPropertyChangedEventArgs)
{
字符串值=(字符串)eventArgs.NewValue;
if(String.IsNullOrWhiteSpace(value))返回;
if(DesignerProperties.GetIsInDesignMode(元素))返回;
如果(!(元素为FrameworkElement))返回;
int指数=0;
如果(!\u计数器容器(值))
_计数器。添加(值、索引);
其他的
索引=++计数器[值];
string name=string.Format(“{0}{1}”,值,索引);
((FrameworkElement)元素)。名称=名称;
((FrameworkElement)元素).RegisterName(名称,元素);
}
公共静态void SetAutoName(DependencyObject元素,字符串值)
{
SetValue(AutoNameProperty,value);
}
公共静态字符串GetAutoName(DependencyObject元素)
{
返回(字符串)元素.GetValue(AutoNameProperty);
}
}
XAML中的用法:
生成的可视化树:
曼弗雷德·拉德维默的解决方案很有用,但使后面的控制代码更难编写 控件的OnApplyTemplate中搜索该模板部分的任何动态代码都将成为一个难题 另一种方法是对自动化id使用相同的技巧(生成唯一id),并在测试中使用自动化id 见:
曼弗雷德·拉德维默的解决方案很有用,但使后面的控制代码更难编写 控件的OnApplyTemplate中搜索该模板部分的任何动态代码都将成为一个难题 另一种方法是对自动化id使用相同的技巧(生成唯一id),并在测试中使用自动化id 见:
非常有用!我在一个SCADA软件中被阻止了,该软件无法在整个应用程序中管理非唯一名称。非常有用!我在一个SCADA软件中被阻止,该软件无法在整个应用程序中管理非唯一名称。
public static class TestingProperties
{
private static readonly Dictionary<string, int> _counter = new Dictionary<string, int>();
public static readonly DependencyProperty AutoNameProperty = DependencyProperty.RegisterAttached(
"AutoName", typeof(string), typeof(TestingProperties), new PropertyMetadata(default(string), OnAutoNamePropertyChanged));
private static void OnAutoNamePropertyChanged(DependencyObject element, DependencyPropertyChangedEventArgs eventArgs)
{
string value = (string) eventArgs.NewValue;
if (String.IsNullOrWhiteSpace(value)) return;
if (DesignerProperties.GetIsInDesignMode(element)) return;
if (!(element is FrameworkElement)) return;
int index = 0;
if (!_counter.ContainsKey(value))
_counter.Add(value, index);
else
index = ++_counter[value];
string name = String.Format("{0}_{1}", value, index);
((FrameworkElement)element).Name = name;
((FrameworkElement)element).RegisterName(name, element);
}
public static void SetAutoName(DependencyObject element, string value)
{
element.SetValue(AutoNameProperty, value);
}
public static string GetAutoName(DependencyObject element)
{
return (string)element.GetValue(AutoNameProperty);
}
}