除了与ElementName
, 绑定之外的其他方式是使用x:Reference但它还需要在x:Name
其上定义目标元素。所以,这超出了这里的范围。
在不定义名称的情况下我能想到的其他方法是绑定如下所示的内容(绑定到父级而不是索引器以获取目标子级)。
但这与您的逻辑树结构紧密耦合-
<StackPanel>
<TextBlock Text="Test"/>
<TextBlock Text="{Binding Parent.Children[0].Text,
RelativeSource={RelativeSource Mode=Self}}"/>
</StackPanel>
此外,这可以使用IValueConverter来实现。正如您所提到的,您的父容器中只有一个此类元素,您可以将父容器传递给转换器,该转换器将使用VisualTreeHelper类遍历子容器。
<StackPanel>
<TextBlock Text="Test"/>
<TextBlock Text="{Binding Parent, RelativeSource={RelativeSource Self},
Converter={StaticResource MyConverter}}"/>
</StackPanel>
这是您的转换器代码-
public class MyConverter: IValueConverter
{
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
if (value is DependencyObject)
{
var textBlock = FindChild<TextBlock>((DependencyObject)value, null);
return (textBlock == null)?string.Empty:textBlock.Text;
}
else
return String.Empty;
}
public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
return Binding.DoNothing;
}
}
下面是使用 VisualTreeHelper 进行遍历的方法。我已将此方法放在我的实用程序类中,在许多情况下都很方便 -
public static T FindChild<T>(DependencyObject parent, string childName)
where T : DependencyObject
{
// Confirm parent is valid.
if (parent == null) return null;
T foundChild = null;
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
// If the child is not of the request child type child
T childType = child as T;
if (childType == null)
{
// recursively drill down the tree
foundChild = FindChild<T>(child, childName);
// If the child is found, break so we do not
// overwrite the found child.
if (foundChild != null) break;
}
else if (!string.IsNullOrEmpty(childName))
{
var frameworkElement = child as FrameworkElement;
// If the child's name is set for search
if (frameworkElement != null
&& frameworkElement.Name == childName)
{
// if the child's name is of the request name
foundChild = (T)child;
break;
}
}
else
{
// child element found.
foundChild = (T)child;
break;
}
}
return foundChild;
}