Russ
Russ

Reputation: 4163

Binding ListBox Items using Templates

I am going crazy trying to figure this out without success.

I have a DependencyObject, ("UserObject"). It has a "DataItems" DependecyProperty that is an ObservableCollection. "UserDefiniton" is a DependencyObject with a DependencyProperty of "Data". Data has two properties: DataType (an enumeration) and Value (a string).

I am trying to define a ListBox in XAML that uses the "DataItems" property as its ItemsSource. In the ItemTemplate, I have several different controls. For simplicity of this issue, I am using a CheckBox and a TextBox. I want CheckBox to be available and visible when DataType is 0, while I want the TextBox to be available and visible when the DataType is 1. Only one control can be available and visible at a time.

This works:

<ListBox
    ItemsSource={Binding DataItems, Mode=OneWay}>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <CheckBox
                    Visibility="{Binding Path=Data.DataType, Mode=OneWay, Converter={StaticResource VisibilityConverter}, ConverterParameter=0}"
                    IsChecked="{Binding Path=Data.Value, Mode=TwoWay, Converter={StaticResource StringToBoolean}}" />
                <TextBox
                    Visibility="{Binding Path=Data.DataType, Mode=OneWay, Converter={StaticResource VisibilityConverter}, ConverterParameter=1}"
                    Text="{Binding Path=Data.Value, Mode=TwoWay}" />
            </StackPanel>
        </DataTemplate>
    <Listbox.ItemTemplate>
</ListBox>

The problem is that even though only one is visible, both are fighting over the Data.Value property (the boolean of the checkbox will show in the textbox, even though the checkbox is hidden).

Basically, though, the binding in this case is working--but the implementation is incorrect.

So, I switched to using Templates. The problem I am having is that I can't get the binding to work.

This is the code that I have for the Template. The Template selector is working correctly, but the Text property of the TextBox and the IsChecked property of the checkbox are not binding to Data.Value:

  <DataTemplate x:Key="TextBoxItem">
                <TextBox
                    Text="{Binding Path=Data.Value, Mode=TwoWay}" />
  </DataTemplate>
  <DataTemplate x:Key="CheckBoxItem">
                <CheckBox
                    IsChecked="{Binding Path=Data.Value, Mode=TwoWay, Converter={StaticResource StringToBoolean}}" />
  </DataTemplate>


...

<ListBox
    ItemsSource={Binding DataItems, Mode=OneWay}>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <ContentControl
                Content="{Binding Path=Data.DataType, Mode=OneWay}"
                         ContentTemplateSelector="{DynamicResource UserDefinitionTemplateSelector}"/>

        </DataTemplate>
    <ListBox.ItemTemplate>
</ListBox>

So how do I fix the binding?

Upvotes: 2

Views: 1808

Answers (1)

brunnerh
brunnerh

Reputation: 184506

Content should be set to {Binding}, since the Content will be the DataContext of the data-templates, hence you should just pass on the current DataContext. If you need to pass specific data to the template selector you can just drill down in the whole object.

There also is a template selector on the level of the ListBox, so you do not really need the internal ContentControl.

(You might also be interested in generic methods of debugging data bindings.)

Upvotes: 4

Related Questions