51
votes

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.

4

4 Answers

30
votes

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 handling.

(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)

22
votes

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.

7
votes

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...

7
votes

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!