2
votes

Is there any way to have a listbox populated by both static and dynamic items?

I am writing a windows phone 7 app and would like to have one static listboxItem at the top or bottom and then bind other items from the viewModel. I tried setting both a static listboxItem and then also a dataTemplate but the static item is replaced by the dynamic items.

Edit:

I have found several posts that show how to create a custom control that inherits from listbox which allows multiple templates. How might I create a custom control which adds a section for static items which are always present regardless of binding.

2

2 Answers

1
votes

If you are trying to do MVVM and are also two-way binding the SelectedItem of the ListBox, it is going to be much easier/cleaner to just bind one collection to the ItemsSource property.

Can you just pre-populate the collection in your ViewModel with the static item? You could then merge your dynamic items into the already existing collection when they are available (coming back from a web service or whatever). It seems like you would want this kind of logic in your ViewModel anyway, and just expose a single list to the View to use with the ListBox.

0
votes

Because there are two different types of items, I think your best bet would be to create a custom ListBox subclass which adds a new DependencyProperty to allow you to bind and display a second list. This would also require a new default style to display the second list appropriately in the same ScrollViewer as the normal <ItemsPresenter/>.

Here is an example of my custom ListBox to allow this:

public class MyListBox : ListBox
{
    public MyListBox()
        : base()
    {
        this.DefaultStyleKey = typeof(MyListBox);
    }

    public static readonly DependencyProperty StaticItemsProperty = DependencyProperty.Register(
        "StaticItems",
        typeof(IList),
        typeof(MyListBox),
        null);

    public IList StaticItems
    {
        get { return (IList)GetValue(StaticItemsProperty); }
        set { SetValue(StaticItemsProperty, value); }
    }
}

You would then have to copy the entire default ListBox style into your themes/generic.xaml resource dictionary and modify it to become the default style for the MyListBox control. The only thing I modified from the default style (aside from the TargetType attribute) was the content of the ScrollViewer which had the original list:

<Style TargetType="custom:MyListBox">
    <!-- all the same old XAML for the normal ListBox -->
    <ScrollViewer x:Name="ScrollViewer" Background="{TemplateBinding Background}" BorderBrush="Transparent" BorderThickness="0" Padding="{TemplateBinding Padding}" TabNavigation="{TemplateBinding TabNavigation}">
        <StackPanel Orientation="Vertical">
            <ItemsControl ItemsSource="{TemplateBinding StaticItems}">
                <ItemsControl.ItemTemplate>
                    <DataTemplate>
                        <TextBox Text="{Binding}"/>
                    </DataTemplate>
                 </ItemsControl.ItemTemplate>
            </ItemsControl>
            <ItemsPresenter/>
        </StackPanel>
    </ScrollViewer>
    <!-- rest of the same old ListBox XAML -->
</Style>

As you can see I modified the ScrollViewer which normally just contained the ItemsPresenter for the ListBox and replaced it with a StackPanel containing a new ItemsControl bound to the new StaticItems DependencyProperty I added to MyListBox. I modified the DataTemplate for this ItemsControl to show a TextBox. The normal ItemsPresenter with the normal ItemsTemplate would then show up below the static list in the ScrollViewer.

This custom ListBox can then be used in place of a normal ListBox to bind to two different lists in your ViewModel, both to your static items and your dynamic items.

<custom:MyListBox x:Name="ListBox" ItemsSource="{Binding DynamicItems}" StaticItems="{Binding StaticItems}"/>