Thursday, February 17, 2011

Binding a DynamicResource

I'm trying to use a MultiBinding as the ItemsSource for a ListBox, and I want to bind a couple of collections to the MultiBinding. The collections aren't populated until after the host control (a derivation of Page) has already been instantiated. Just after being constructed, I call a method that sets up some of the data for the Page, including these collections.

Right now, I have something like this:

public void Setup()
{
    var items = MyObject.GetWithID(backingData.ID); // executes a db query to populate collection  
    var relatedItems = OtherObject.GetWithID(backingData.ID);
}

and I want to do something like this in XAML:

<Page ...

  ...

    <ListBox>
        <ListBox.ItemsSource>
            <MultiBinding Converter="{StaticResource converter}">
                <Binding Source="{somehow get items}"/>
                <Binding Source="{somehow get relatedItems}"/>
            </MultiBinding>
        </ListBox.ItemsSource>
    </ListBox>
  ...
</Page>

I know I can't use DynamicResource in a Binding, so what can I do?

From stackoverflow
  • Sounds to me like what you really want is a CompositeCollection and to setup a DataContext for your Page.

    <Page x:Class="MyPage" DataContext="{Binding RelativeSource={RelativeSource Self}}">
        <Page.Resources>
            <CollectionViewSource Source="{Binding Items}" x:Key="items" />
            <CollectionViewSource Source="{Binding RelatedItems}" x:Key="relatedItems" />
        </Page.Resources>
    
        <ListBox>
           <ListBox.ItemsSource>
             <CompositeCollection>
               <CollectionContainer
                 Collection="{StaticResource items}" />
               <CollectionContainer
                 Collection="{StaticResource relatedItems}" />
             </CompositeCollection>
           </ListBox.ItemsSource>
        </ListBox>
    </Page>
    

    The Code behind would look something like this:

    public class MyPage : Page
    {
        private void Setup()
        {
            Items = ...;
            RelatedItems = ...;
        }
    
        public static readonly DependencyProperty ItemsProperty =
            DependencyProperty.Register("Items", typeof(ReadOnlyCollection<data>), typeof(MyPage),new PropertyMetadata(false));
        public ReadOnlyCollection<data> Items
        {
            get { return (ReadOnlyCollection<data>)this.GetValue(ItemsProperty ); }
            set { this.SetValue(ItemsProperty , value); } 
        }
    
        public static readonly DependencyProperty RelatedItemsProperty =
            DependencyProperty.Register("RelatedItems", typeof(ReadOnlyCollection<data>), typeof(MyPage),new PropertyMetadata(false));
        public ReadOnlyCollection<data> RelatedItems
        {
            get { return (ReadOnlyCollection<data>)this.GetValue(RelatedItemsProperty ); }
            set { this.SetValue(RelatedItemsProperty , value); } 
        }
    }
    

    Edit: I remembered that CollectionContainer doesn't participate in the logical tree so you need to use a CollectionViewSource and a StaticResource.

0 comments:

Post a Comment