Bill Palmer
Bill Palmer

Reputation: 41

WPF Element Binding in a within a Resource control doesnt work

I have some xaml that will just copy text from one text box to another:

<StackPanel   Orientation="Horizontal">
    <TextBox Width="100" Height="30" Text="{Binding ElementName=src1, Path=Text}"  />
    <TextBox x:Name="src1" Width="100" Height="30" />
</StackPanel>

Nothing special, works fine. A bit dumb but just an example. However if I put the StackPanel as a resource in the Window and create dynamically from code, like this:

<Window.Resources>
    <StackPanel  x:Key="MySP" Orientation="Horizontal">
        <TextBox Width="100" Height="30" Text="{Binding ElementName=src, Path=Text}"/>
        <TextBox x:Name="src" Width="100" Height="30" />
    </StackPanel>
</Window.Resources>

.. then the element binding doesnt work anymore.

Why? and how to make it work? Any ideas gratefully received.

Upvotes: 4

Views: 2238

Answers (3)

David
David

Reputation: 10708

Having a similar issue, trying to get relative binding to my source control - In my case, I'm creating a designer and need the element as a static so styles can use it's dimensions for centering calculations on a canvas.

Taking a line from [WPF Xaml Namescopes],

ResourceDictionary does not use XAML names or namescopes ; it uses keys instead, because it is a dictionary implementation.

So, directly using ElementName in a resource Dictionary simply does not work, because no name will bind without a NameScope. Also attempted reproducing your situation with Style setters, but no luck - one cannot set an object's name via a Style.

Now, the convoluted solution I cam up with is to

  1. Create a DependencyProperty in the code-behind of the class you're declaring this resource in.
  2. replace ElementName=Root with RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type namespace:RootClass}} and bind to said container directly, allowing you to bind to said DependencyProperty whilst bypassing the names.
  3. If you need bindings to operate between two elements in the same StaticResource, bind the source to said DependencyProperty as OneWayToSource or TwoWay, and the destination as OneWay or TwoWay.

1

Upvotes: 0

Fredrik Hedblad
Fredrik Hedblad

Reputation: 84666

The following Xaml should work just fine

<Window ...>
    <Window.Resources>
        <StackPanel x:Key="MySP" Orientation="Horizontal">
            <TextBox Width="100" Height="30" Text="{Binding ElementName=src, Path=Text}"/>
            <TextBox x:Name="src" Width="100" Height="30" />
        </StackPanel>
    </Window.Resources>
    <StaticResource ResourceKey="MySP"/>
</Window>

You could also use it from code

StackPanel mySP = TryFindResource("MySP") as StackPanel;
if (mySP != null)
{
    this.Content = mySP;
}

However, what is the reason for you to have a StackPanel in the Windows Resoures?
If you want to be able to reuse it several times you would have to set x:Shared="False" on the Resource but then you'll get an exception saying something like Cannot register duplicate Name 'src' in this scope the second time you add it.

Upvotes: 2

321X
321X

Reputation: 3185

As far as I'm concerned you should not put that in <Window.Resources>. Only styles, static, dynamic resources and such...

http://msdn.microsoft.com/en-us/library/ms750613.aspx

<Window>
    <Window.Resources>
    </Window.Resources>
    <StackPanel  x:Key="MySP" Orientation="Horizontal">
        <TextBox Width="100" Height="30" Text="{Binding ElementName=src, Path=Text}"/>
        <TextBox x:Name="src" Width="100" Height="30" />
    </StackPanel>
<Window>

Upvotes: 1

Related Questions