Are "{Binding Path=.}" and "{Binding}" really equal
Asked Answered
M

4

54

In my WPF project, I have a ListBox that displays items from a List<string> collection. I wanted to make the text of these items editable, so I wrapped each of them in an ItemTemplate with a TextBox (might not be the best way, but I'm new to WPF). I was having trouble simply binding the TextBoxes' Text property to the value of each item. I finally stumbled upon an example using a single dot or period for its Path property ({Binding Path=.}):

<ListBox ItemsSource="{Binding ElementName=recipesListbox,Path=SelectedItem.Steps}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBox Text="{Binding Path=.}"/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

However I don't understand why simply using {Binding} didn't work.

It raised a "Two-way binding requires Path or XPath" exception, as according to Microsoft:

[...] a period (.) path can be used to bind to the current source. For example, Text="{Binding}" is equivalent to Text="{Binding Path=.}"

Could someone shed light on this ambiguous behavior?

EDIT: Moreover, it seems {Binding Path=.} does not necessarily give two-way binding, as modifying the text and moving the focus does not update the underlying source (the same source has also properties displayed and successfully modified on a DataGrid control). I'm definitely missing something here.

Michale answered 30/3, 2011 at 14:54 Comment(0)
C
34

The point of the exception presumably is that you cannot two-way bind a binding-source itself, so it tries to prevent you from creating a binding which does not behave the way you would want it to. By using {Binding Path=.} you just trick the error detection.

(Also it's not unheard of that documentation is erroneous or inaccurate, though i do like the MSDN documentation a lot in general as it usually does contain the crucial points one is interested in)

Circumstantiate answered 3/8, 2012 at 23:46 Comment(3)
+1: This is the correct answer. I just encountered this phenomenon myself.Waterresistant
But Two Way binding STILL fails. It refuses to save the changes. If you have an ObsColl<int> and do Path=. Mode=TwoWay binding, adding to the collection works fine. Changing the number at index 0 for example wont. If you bind a datagrid to it and specify a datagridtextcolumn, it refuses to save with Path=.Psychopharmacology
@user999999928: That is what i have been saying: You just trick the error handling. You make an error that is not detected, you still won't get the binding you want as you still bind to the source which cannot detect changes.Circumstantiate
S
23

The documentation states that {Binding} is equivalent to {Binding Path=.}. However it is not equivalent to {Binding Path} as you have typed. If you include the Path property, you must assign it to something, be it Path=. or Path=OtherProperty.

Sermonize answered 30/3, 2011 at 15:11 Comment(2)
That was a typo, it's fixed now.Michale
But Two Way binding STILL fails. It refuses to save the changes. If you have an ObsColl<int> and do Path=. Mode=TwoWay binding, adding to the collection works fine. Changing the number at index 0 for example wont. If you bind a datagrid to it and specify a datagridtextcolumn, it refuses to save with Path=.Psychopharmacology
F
8

In short, the difference between the two is analogous with the difference between the traditional pass by value and pass by reference. (FYR - What's the difference between passing by reference vs. passing by value?)

However I don't understand why simply using {Binding} didn't work (it raised a "Two-way binding requires Path or XPath" exception)

Lets assume here for now that {Binding} can be used for two way binding. In general {Binding} creates a value based link with datacontext which does not allow updating the datacontext.

Whereas {Binding Path=.} creates reference based link with the memory area referenced by the 'Path' which allows updating the value through reference.(in this case 'dot' the current datacontext).

Hope this helps!

Frambesia answered 6/3, 2015 at 11:40 Comment(1)
using ByRef and ByVal atleast gave me an idea on how to differentiate the two bindings (with Path and w/o). Thanks!Flavor
A
7

These are not the same. If you bind this where ConsoleMessages is an ObservableCollection string with just {Binding} you get a "Two-way binding requires Path or XPath." exception where as {Binding Path=.} works. This is with WPF 4.0...

    <ItemsControl x:Name="ConsoleOutput" ItemsSource="{Binding ConsoleMessages, Mode=OneWay}" MaxHeight="400">
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <TextBox Text="{Binding Path=.}" BorderThickness="0" Margin="0" />
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>

My 2p worth...

Amenable answered 14/7, 2011 at 13:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.