0

I have an ObservableCollection that I try to bind to a list of text boxes. The textboxes do show but the content of the text does not.

The XAML:

<Grid>
    <Grid.RowDefinitions >
        <RowDefinition />
    </Grid.RowDefinitions>
    <ItemsControl ItemsSource="{Binding Path=ListOfMessages}" >
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <TextBox Text="{Binding Path=Message, ElementName=ListOfMessages}" />
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>

The Code:

In the ViewModel:

public ObservableCollection<ApplicationLog> ListOfMessages { get; set; }

In the Model:

public class ApplicationLog 
{
    public string Code { get; set; }
    public string Message { get; set; }
}

When I run this, the app shows the text boxes (for example 4 text boxes, one below the other), but the text in the text boxes (ie the Message property) is not shown. I think my Binding expression for the Text Box is wrong.

Context: I am new to XAML and WPF. More generally: how does one debug Binding issues similar to this one.

Thanks.

Frank Monroe
  • 1,557
  • 2
  • 13
  • 20
  • If you look in the output window while debugging, you should see the Binding error giving you a hint. – Mark W Apr 08 '17 at 03:55
  • Thanks. But I have difficulty reading: System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=ListOfMessages'. BindingExpression:Path=Message; DataItem=null; target element is 'TextBox' (Name=''); target property is 'Text' (type 'String') This tells me the binding does not work - what else can I infer? – Frank Monroe Apr 08 '17 at 04:17
  • That is telling you that the datacontext is trying to bind to ListOfMessages.Message. The ObservableCollection does not have a property of "Message"... as you've seen in the answer. The datacontext of any list item is the item of the collection. Glad you got it worked out. – Mark W Apr 10 '17 at 12:39

1 Answers1

1

Remove ElementName=ListOfMessages. The DataContext for each item will be the items in the ListOfMessages bound to the ItemsSource.

<Grid>
    <Grid.RowDefinitions >
        <RowDefinition />
    </Grid.RowDefinitions>
    <ItemsControl ItemsSource="{Binding Path=ListOfMessages}" >
        <ItemsControl.ItemTemplate>
            <DataTemplate>
                <!-- DataContext will be ListOfMessages[0], [1], ..., [n] -->
                <TextBox Text="{Binding Path=Message}" /> 
            </DataTemplate>
        </ItemsControl.ItemTemplate>
    </ItemsControl>
</Grid>

ElementName is used to bypass the DataContext and point to a specific named item in your scoped XAML.

Laith
  • 6,071
  • 1
  • 33
  • 60
  • Thanks; that did it! What got me it that Intellisense underlined (in blue) "Message" in the XAML with tip "Cannot resolve symbol 'Message'" (in VS2017); so I did not even tried. Why does Intellisense gave me this message? – Frank Monroe Apr 08 '17 at 04:14
  • Intellisense doesn't know where `ListOfMessages` is coming from. You need to use `d:DataContext` on the root element in your xaml. Look at this post for example http://stackoverflow.com/questions/15101696/what-do-i-need-to-further-qualify-the-datacontext-for-a-binding – Laith Apr 08 '17 at 04:22