除了與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遍歷方法。我把這種方法放在我的Utility類中,在很多情況下很方便 -
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;
}
我會說使用'x:Name',因爲您可能想出的任何其他解決方案都會更復雜且效率更低。 –
@Sniffer我很感興趣,看看是否有其他選擇。 –