Binding to a TextBox inside a Style for a ListBoxItem
Hi!
I'm having a bit of trouble adding items to a listbox for which I've made an item style.
The idea is that a TextBox contained within the style should be bound to a property of my data items, in this case ModelName. I set the binding to ModelName inside the TextBox, set the ItemsSource property for the ListBox, as well as the item container style, and a DataContext containing items which expose a ModelName property, but this approach is failing. The listbox does get populated as I add items to it, but my textboxes are blank. I tried using a two-way binding, but that did not work either.
To start with, here is my list box item style:
... and here is the ListBox to whose items it is applied ...
Here are my data context and items wrapper classes:
and here is where I initialize my listbox, set data context and item style:
When I add items, I do the following:
This creates a new DataItem with a ModelName property, which should be bound to the textbox. However, I cannot get this to work. If I use a DataTemplate rather than a Style, the binding works, but I have other problems.
Any ideas?
Thanks
I'm having a bit of trouble adding items to a listbox for which I've made an item style.
The idea is that a TextBox contained within the style should be bound to a property of my data items, in this case ModelName. I set the binding to ModelName inside the TextBox, set the ItemsSource property for the ListBox, as well as the item container style, and a DataContext containing items which expose a ModelName property, but this approach is failing. The listbox does get populated as I add items to it, but my textboxes are blank. I tried using a two-way binding, but that did not work either.
To start with, here is my list box item style:
Code: Select all
<Style x:Key="ListBoxItemModelLayerStyle" TargetType="{x:Type ListBoxItem}">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="HorizontalContentAlignment" Value="{Binding HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="VerticalContentAlignment" Value="{Binding VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"/>
<Setter Property="Padding" Value="2,0,0,0"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListBoxItem}">
<Grid x:Name="GridTemplate" HorizontalAlignment="Stretch" Height="60" Margin="0" VerticalAlignment="Top" Width="168" Visibility="Visible">
<Rectangle x:Name="RectangleTemplate" RadiusY="5" RadiusX="5" Fill="#BF6C87CC"/>
<TextBox x:Name="ModelNameTextBoxTemplate" Margin="32.5,5,0,0" TextWrapping="Wrap" Text="{Binding ModelName}" FontSize="12" Background="#FF5368A1" Foreground="#FFDADADA" Height="25" VerticalAlignment="Top" Width="130" HorizontalAlignment="Left" BorderBrush="{x:Null}"/>
<ComboBox x:Name="ModelTypeComboBoxTemplate" Height="24" Margin="32,0,0,5" VerticalAlignment="Bottom" Width="79" HorizontalAlignment="Left" Background="#FF6781C3" Foreground="Black" BorderBrush="{x:Null}">
<ComboBoxItem x:Name="ModelTypeBoxUpperTemplate" Content="Upper"/>
<ComboBoxItem x:Name="ModelTypeBoxLowerTemplate" Content="Lower"/>
<ComboBoxItem x:Name="ModelTypeBoxBuccalTemplate" Content="Buccal"/>
</ComboBox>
<ToggleButton x:Name="ModelToggleVisibilityButtonTemplate" Content="ToggleButton" HorizontalAlignment="Left" Margin="3,0,0,0" Style="{DynamicResource ToggleVisibilityEye}" Width="25" IsChecked="True" VerticalAlignment="Center" Height="25"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Code: Select all
<ListBox x:Name="ItemLayersListBox" ItemsSource="{Binding Items}" HorizontalAlignment="Center" Margin="0" Width="200" VerticalAlignment="Center" MaxHeight="720" Background="{x:Null}" BorderBrush="{x:Null}" Foreground="{x:Null}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollBarVisibility="Hidden" MinHeight="200">
<ListBoxItem Content="ModelLayer" Style="{DynamicResource ListBoxItemModelLayerStyle}"/>
</ListBox>
Code: Select all
class DataModel : public Noesis::Core::BaseComponent
{
public:
DataModel() : items_(new Noesis::Gui::Collection())
{ }
~DataModel()
{
}
Noesis::Gui::Collection* GetItems() const { return items_; }
private:
Noesis::Gui::Collection* items_;
NS_IMPLEMENT_INLINE_REFLECTION(DataModel, Noesis::Core::BaseComponent)
{
NsMeta<Noesis::Core::TypeId>("DataModel");
NsProp("Items", &DataModel::GetItems);
}
};
Code: Select all
struct DataItem : public Noesis::Core::BaseComponent
{
DataItem(const NsChar* n) :
name_(n)
{
}
NsString name_;
NsString type_;
NS_IMPLEMENT_INLINE_REFLECTION(DataItem, Noesis::Core::BaseComponent)
{
NsMeta<Noesis::Core::TypeId>("DataItem");
NsProp("ModelName", &DataItem::name_);
}
};
Code: Select all
auto list_box = NsStaticCast<ListBox*>(gui_root_->FindName(LISTBOX_NAME.c_str()));
data_model_ = new DataModel();
Ptr<IResourceKey> key = ResourceKeyString::Create("ListBoxItemModelLayerStyle");
Noesis::Gui::Style* style = gui_root_->FindResource<Noesis::Gui::Style>(key.GetPtr());
list_box->SetDataContext(data_model_);
list_box->SetItemContainerStyle(style);
Code: Select all
data_model_->GetItems()->Add(new DataItem(_name.c_str()));
Any ideas?
Thanks
-
-
sfernandez
Site Admin
- Posts: 3203
- Joined:
Re: Binding to a TextBox inside a Style for a ListBoxItem
Hi,
First of all, if you use the ItemsSource property, the ListBox.Items collection is made read only and you cannot add/remove items from there, so you shouldn't specify any ListBoxItem children inside the ListBox. The following xaml is wrong (we will add the corresponding error message in a following version):
Second, when you use the ItemsSource property, a ListBoxItem container is automatically created for each item, so if you want to specify a Style for these containers, you have to do it using ItemContainerStyle property:
Next, to understand how data binding works in a ListBox I made this graphic representing the generated visual tree:
As you can see, your DataItems are connected through the DataContext property to the root of the DataTemplate you specify in the ItemTemplate property. The ListBoxItem and its template elements know nothing about the DataItem, so they cannot have a Binding to DataItem properties. These bindings only work for elements in the ItemTemplate's DataTemplate.
Which problems do you have when using a DataTemplate?
First of all, if you use the ItemsSource property, the ListBox.Items collection is made read only and you cannot add/remove items from there, so you shouldn't specify any ListBoxItem children inside the ListBox. The following xaml is wrong (we will add the corresponding error message in a following version):
Code: Select all
<ListBox ItemsSource="{Binding Items}" ...>
<ListBoxItem .../> <!-- WRONG -->
</ListBox>
Code: Select all
<ListBox
ItemsSource="{Binding Items}"
ItemContainerStyle="{StaticResource ContainerStyle}" .../>
As you can see, your DataItems are connected through the DataContext property to the root of the DataTemplate you specify in the ItemTemplate property. The ListBoxItem and its template elements know nothing about the DataItem, so they cannot have a Binding to DataItem properties. These bindings only work for elements in the ItemTemplate's DataTemplate.
Which problems do you have when using a DataTemplate?
Re: Binding to a TextBox inside a Style for a ListBoxItem
Thank you for the very detailed explanation!
So it looks as though using a Style will not work for my purposes, as I need the fields bound to item properties.
Regarding DataTemplates, when I was using a DataTemplate containing a styled ToggleButton, the style wasn't being properly applied to the ToggleButton when I dynamically added items to the listbox.
Here is the DataTemplate I was using before (the ToggleButton Style below is ToggleVisibilityEye):
That Style uses a stroked path graphic to toggle the visibility of items referenced in the listbox. But when applying the template to dynamically added items, I see a default-styled ToggleButton with some text that appears to say "To" (as in ToggleButton maybe?), rather than the properly styled button.
Is there something I'm doing wrong there in using the DataTemplate?
So it looks as though using a Style will not work for my purposes, as I need the fields bound to item properties.
Regarding DataTemplates, when I was using a DataTemplate containing a styled ToggleButton, the style wasn't being properly applied to the ToggleButton when I dynamically added items to the listbox.
Here is the DataTemplate I was using before (the ToggleButton Style below is ToggleVisibilityEye):
Code: Select all
<DataTemplate x:Key="ModelLayerTemplate">
<Grid HorizontalAlignment="Left" Height="60" Margin="0,0,0,0" VerticalAlignment="Top" Width="190">
<Rectangle RadiusY="5" RadiusX="5" Fill="#BF95ACE5"/>
<TextBox x:Name="ModelNameTextBox" Margin="32.5,5,0,0" TextWrapping="Wrap" Text="{Binding ModelName}" FontSize="12" Background="#FF5368A1" Foreground="#FFDADADA" Height="25" VerticalAlignment="Top" Width="130" HorizontalAlignment="Left" BorderBrush="{x:Null}"/>
<ComboBox x:Name="ModelTypeComboBox" Height="24" Margin="32,0,0,5" VerticalAlignment="Bottom" Width="79" HorizontalAlignment="Left">
<ComboBoxItem x:Name="ModelTypeBoxUpper" Content="Upper" IsSelected="True"/>
<ComboBoxItem x:Name="ModelTypeBoxLower" Content="Lower"/>
<ComboBoxItem x:Name="ModelTypeBoxBuccal" Content="Buccal"/>
</ComboBox>
<ToggleButton x:Name="ModelToggleVisibilityButton" Content="ToggleButton" HorizontalAlignment="Left" Margin="3,0,0,0" Style="{DynamicResource ToggleVisibilityEye}" Width="25" IsChecked="True" VerticalAlignment="Center" Height="25"/>
</Grid>
</DataTemplate>
Is there something I'm doing wrong there in using the DataTemplate?
-
- KeldorKatarn
- Posts: 237
- Joined:
Re: Binding to a TextBox inside a Style for a ListBoxItem
I'm not sure if I remember this right but... can't you declare that DataTemplate as a resource, and then in the style itself reference that datatemplate, assigning it not directly but in the style... would that work?
-
-
sfernandez
Site Admin
- Posts: 3203
- Joined:
Re: Binding to a TextBox inside a Style for a ListBoxItem
I was able to reproduce the problem. There is a bug with DynamicResource look up. We will fix it in the next release. Meanwhile you can use a StaticResource instead:Regarding DataTemplates, when I was using a DataTemplate containing a styled ToggleButton, the style wasn't being properly applied to the ToggleButton when I dynamically added items to the listbox.
Is there something I'm doing wrong there in using the DataTemplate?
Code: Select all
<DataTemplate x:Key="ModelLayerTemplate">
<Grid HorizontalAlignment="Left" Height="60" Margin="0,0,0,0" VerticalAlignment="Top" Width="190">
...
<ToggleButton x:Name="ModelToggleVisibilityButton" Content="ToggleButton" HorizontalAlignment="Left" Margin="3,0,0,0" Style="{StaticResource ToggleVisibilityEye}" Width="25" IsChecked="True" VerticalAlignment="Center" Height="25"/>
</Grid>
</DataTemplate>
Re: Binding to a TextBox inside a Style for a ListBoxItem
Thanks! I'll try the StaticResource approach for now.
-
-
sfernandez
Site Admin
- Posts: 3203
- Joined:
Re: Binding to a TextBox inside a Style for a ListBoxItem
DynamicResource look-up solved in 1.1.9 version.
Who is online
Users browsing this forum: No registered users and 8 guests