在XAML中绑定到Self /'this'

时间:2010-10-01 09:01:11

标签: c# wpf xaml

简单的WPF / XAML问题。在XAML中,如何在给定的上下文中引用Self / this对象?在具有主窗口,一个控件和窗口的编码C#属性的非常基本的应用程序中,我想将控件的属性绑定到窗口的手写编码属性。

在代码中,这很容易 - 在Window的构造函数中,我添加了这个:

Binding bind = new Binding();
bind.Source = this;
bind.Path = new PropertyPath("ButtonWidth");
button1.SetBinding(WidthProperty, bind);

显然,我有一个名为ButtonWidth的属性,以及一个名为button1的控件。我无法弄清楚如何在XAML中执行此操作。以下示例的各种尝试都没有奏效:

<Button x:Name="button1" Width="{Binding Source=Self Path=ButtonWidth}"/>

<Button x:Name="button1" Width="{Binding RelativeSource={RelativeSource Self} Path=ButtonWidth}"/> 

由于

5 个答案:

答案 0 :(得分:76)

首先在Binding中使用RelativeSource和Path之间的逗号:

<Button x:Name="button1" Width="{Binding RelativeSource={RelativeSource Self}, 
                                Path=ButtonWidth}"/> 

其次,RelativeSource绑定到Button。 Button没有名为ButtonWidth的属性。我猜你需要绑定到你的父控件。

所以试试这个RelativeSource绑定:

<Button x:Name="button1" Width="{Binding RelativeSource=
    {RelativeSource FindAncestor, AncestorType={x:Type YourNamespace:YourParentControl}}, 
    Path=ButtonWidth}"/> 

答案 1 :(得分:29)

我必须处理RelativeSource之类的一种方法是命名根XAML元素:

<Window x:Class="TestApp2.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"
    x:Name="_this"
    >
    <Grid>
        <Button x:Name="button" Width="{Binding ElementName=_this,Path=ButtonWidth}" />
    </Grid>
</Window>

如果你想设置DataContext,你也可以这样做:

<Window x:Class="TestApp2.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"
    x:Name="_this"
    >
    <Grid DataContext="{Binding ElementName=_this}">        
        <Button x:Name="button" Width="{Binding Path=ButtonWidth}" />
    </Grid>
</Window>

我发现这是一个很好的技巧,不必记住RelativeSource绑定的所有复杂性。

答案 2 :(得分:29)

我认为你在寻找的是:

<Window x:Class = "blah blah all the regular stuff"

DataContext="{Binding RelativeSource={RelativeSource Self}}"

>

答案 3 :(得分:4)

问题with naming the XAML root element是,如果你养成了对项目中所有根使用相同名称(即“_this”,“Root”等)的习惯,那么后期绑定在嵌套模板中可能会访问错误的元素。这是因为,在{Binding}中使用ElementName=... Template时,会在运行时通过向上走NameScope树来解析名称,直到找到第一个匹配项。

Clint's solution避免命名根元素,但它将根元素设置为自己的DataContext,如果数据需要DataContext,则可能不是一个选项。为了提供对它的访问,在元素上引入另一个绑定似乎有点笨拙。之后,如果不再需要访问权限,那么{Binding}将变得混乱:正确访问的责任属于目标和绑定。

因此,这里有一个简单的标记扩展来访问XAML根元素而不命名它:

using System.Xaml;
using System.Windows.Markup;

public sealed class XamlRootExtension : MarkupExtension
{
    public override Object ProvideValue(IServiceProvider sp)
    {
        var rop = sp.GetService(typeof(IRootObjectProvider)) as IRootObjectProvider;
        return rop == null ? null : rop.RootObject;
    }
};

<强> XAML

<Window x:Class="MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:global="clr-namespace:">

    <TextBlock Text="{Binding Source={global:XamlRoot},Mode=OneTime}" />

</Window>

note :为清楚起见,我没有在命名空间中定义MarkupExtension;使用如此处所示的空clr-namespace别名确实实际上用于访问global::命名空间(尽管VS2013设计师似乎抱怨它)。

<强>结果

enter image description here
一个内容与自身绑定的窗口。


<强> n.b。

答案 4 :(得分:0)

不幸的是,使用&#34; ElementName = ..&#34;命名根元素。似乎是UWP的唯一方法,因为那里不支持{RelativeSource Self}。

奇怪的是,当布局中覆盖名称时,这仍然有效,例如

<UserControl x:Class="Path.MyClass" x:Name="internalName">
   <Border Background={Binding Path=Background, ElementName=internalName}" ...

然后

<Page>
   <local:MyClass x:Name=externalName />

</Page>
BTW,Windows 10修复了一个错误(存在于Windows 8.1中),当相同的内部名称用于同一布局中的不同元素时。

不过,我更喜欢使用{RelativeSource Self},因为它对我来说更合乎逻辑,更安全。