标记属性

时间:2015-10-01 03:16:00

标签: c# wpf data-binding

<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>
正如上面的一个简单代码,但绑定无法找到Element myGrid。在运行期间,错误显示在“输出”窗口

  

&#34; System.Windows.Data错误:4:找不到绑定源   引用&#39; ElementName = myGrid&#39;。 BindingExpression:路径= ActualWidth的;   的DataItem = NULL;目标元素是&#39;标签&#39; (名称=&#39;&#39);目标属性是   &#39;内容&#39; (键入&#39;对象&#39;)&#34;

我正在使用Visual Studio 2015社区版和.Net Framework 4.5.2。有任何想法吗?提前谢谢。

3 个答案:

答案 0 :(得分:15)

元素(其属性已绑定)应该是可视树的一部分,以便可以进行可视树搜索。在使用ElementNameRelativeSource绑定时,它会执行一些内部可视树搜索。但是在您的代码中LabelTag的可视树断开连接。 Label只是内存中的一个对象,由Tag属性引用。

从.NET 4.0开始,您可以使用{x:Reference}标记,如下所示:

<Grid.Tag>
    <Label Content="{Binding ActualWidth, Source={x:Reference myGrid}}" />
</Grid.Tag>

修改

如果引用名称指向包含{x:Reference}的某个元素,则使用{x:Reference}会导致出现循环依赖性问题。在您的情况下,它是myGrid(包含{x:Reference})。所以它不能用在你的情况下。相反,你需要使用一些代理。这种技术看起来有点笨拙,但实际上它非常漂亮。它也适用于任何版本的.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>

如您所见,Binding的Source设置为StaticResource指向DiscreteObjectKeyFrame。这是一个Freezable对象,因此无论您使用Freezable还是ElementName,为RelativeSource对象的任何DependencyProperty设置的所有Binding都能正常运行,这非常有趣。因此,我们将其Value属性绑定到Grid(名称为myGrid)。稍后,我们将Content Label属性绑定到Freezable对象,但Path设置为Value.ActualWidthValue指向{{1}因此我们需要附加Grid以将其绑定到ActualWidth)。

事实上,您可以使用任何Grid.ActualWidth对象,但为方便起见,我们使用FreezableDiscreteObjectKeyFrame接受各种Value

还有另一种技术可以在这种情况下设置Binding(断开连接的上下文),但它需要您创建自定义object。它当然更复杂(但是一旦你熟悉WPF,它仍然很简单)。

答案 1 :(得分:0)

我在WPF中尝试了以下代码片段并且工作正常。

<Window x:Class="WpfApplication1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Grid x:Name="myGrid">
    <Grid.Tag>
        <Label Content="{Binding ActualWidth, ElementName=myGrid}" />
    </Grid.Tag>
</Grid>

答案 2 :(得分:0)

我也尝试复制问题,但是在VS 2010中,代码正常工作。

<Window x:Class="CustomEventHandlerClick.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:CustomEventHandlerClick"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <Grid x:Name="myGrid">
        <Grid.Tag>
            <Label Content="{Binding ActualWidth, ElementName=myGrid}"/>
        </Grid.Tag>
    </Grid>
   </Grid>