Jun*_*oic 1 c# data-binding wpf
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:son"
x:Class="son.SonWindow">
<Grid x:Name="myGrid">
<Grid.Tag>
<Label Content="{Binding ActualWidth, ElementName=myGrid}" />
</Grid.Tag>
</Grid>
</UserControl>
Run Code Online (Sandbox Code Playgroud)
就像上面的一个简单代码一样,但是绑定找不到Element myGrid.在运行时,错误显示在"输出"窗口中
"System.Windows.Data错误:4:无法找到与引用'ElementName = myGrid'绑定的源.BindingExpression:Path = ActualWidth; DataItem = null;目标元素是'Label'(Name =''); target属性是'内容'(类型'对象')"
我正在使用Visual Studio 2015社区版与.Net Framework 4.5.2.有任何想法吗?先感谢您.
Hop*_*ess 15
元素(其属性已绑定)应该是可视树的一部分,以便可以进行可视树搜索.使用ElementName或使用Binding时RelativeSource,它会执行一些内部可视树搜索.但是在你的代码中,Label它与视觉树断开了Tag.Label只是内存中的一个对象,由Tag属性引用.
从.NET 4.0开始,您可以使用{x:Reference}标记,如下所示:
<Grid.Tag>
<Label Content="{Binding ActualWidth, Source={x:Reference myGrid}}" />
</Grid.Tag>
Run Code Online (Sandbox Code Playgroud)
编辑:
{x:Reference}如果引用名称指向包含的某个元素,则使用会导致循环依赖性问题{x:Reference}.在你的情况下它是myGrid(包含{x:Reference}).所以它不能用在你的情况下.相反,你需要使用一些代理.这种技术看起来有点hacky,但事实上它非常漂亮.它也适用于任何版本的.NET(支持WPF):
<Grid x:Name="myGrid">
<Grid.Resources>
<DiscreteObjectKeyFrame x:Key="proxy" Value="{Binding ElementName=myGrid}"/>
</Grid.Resources>
<Grid.Tag>
<Label Content="{Binding Value.ActualWidth, Source={StaticResource proxy}}" />
</Grid.Tag>
</Grid>
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,Binding使用其Source设置StaticResource指向a DiscreteObjectKeyFrame.这是一个Freezable对象,所以非常有趣的是,Freezable无论你使用什么,ElementName或者为对象的任何DependencyProperty设置的所有Bindings都能正常工作RelativeSource.所以我们将其Value属性绑定到Grid(名称为myGrid).稍后我们将Content属性绑定Label到Freezable对象,但Path设置为Value.ActualWidth(Value指向Grid,所以我们需要追加ActualWidth绑定它Grid.ActualWidth).
实际上你可以使用任何Freezable对象,但我们使用它是DiscreteObjectKeyFrame为了方便,它Value接受各种各样的object.
还有另一种技术可以在这种情况下设置Binding(断开连接的上下文),但它需要您创建自定义MarkupExtension.它当然更复杂(但是一旦你熟悉WPF,它仍然很简单).