Ryan Amies
Ryan Amies

Reputation: 4922

Use a window resource in a DataTemplate with MVVM

I have a DataTemplate that is loading a list of ~7000 items in a list for a combobox. Currently the ItemsSource is bound to a property in the data context of the DataTemplate, however this means that for each instance of the DataTemplate the system is loading all 7k objects, which is slowing down the system by quite a bit.

Ideally I want to be able to load the list once and use it for all instances. The obvious solution to me is using a resource defined in the Window.Resources section. However I can't figure out how this should work, and more importantly, how that resource should be populated via the MVVM pattern.

Current code which loads the ItemsSource for each DataTemplate instance

<DataTemplate>          
        <ComboBox SelectedItem="{Binding SelectedItem}" ItemsSource="{Binding ItemsSource}" />          
</DataTemplate>

Attempt at solving the problem:

<Window.Resources>
    <ResourceDictionary>           
        <sys:Object x:Key="ItemItemsSource"  />
    </ResourceDictionary>
</Window.Resources>

<DataTemplate>          
        <ComboBox SelectedItem="{Binding SelectedItem}" ItemsSource="{Binding Source={StaticResource ItemItemsSource}}" />          
</DataTemplate>

Update

Each DataTemplate has its own DataContext which means each instance of the data template has its own ItemsSource, which will populate at DataContext initialiser.

Update 2

The ideal way in my mind to solve this is to have a property in the DataContext/VM of the Window that they Combobox is bound too. Is this possible? Something like:

public class WindowsViewModel
{
     public List<Object> SharedItemSource { get; set; }
}

<DataTemplate>          
    <ComboBox SelectedItem="{Binding SelectedItem}" ItemsSource="{Binding <Some Binding To SharedItemSource>}" />          
</DataTemplate>

Upvotes: 0

Views: 490

Answers (3)

eran otzap
eran otzap

Reputation: 12533

Create a MainViewModel for your window or what ever control all your combobox's are in ,

cs:

 public class MainViewModel
 {
    private List<object> _itemsSource;

    public List<object> ItemsSource
    {
        get { return _itemsSource; }
        set { _itemsSource = value; }
    }                
 }

xaml:

       <DataTemplate>
            <ComboBox SelectedItem="{Binding SelectedItem}" 
                  ItemsSource="{Binding Path=DataContext.ItemsSource,
                                 RelativeSource={RelativeSource AncestorType=ItemsControl}}"/>
       </DataTemplate>

Upvotes: 1

Florent
Florent

Reputation: 108

Where is the slow down ?

If it is when you show the ComboBox's popup, maybe you can try to use virtualization like this :

<DataTemplate>          
    <ComboBox SelectedItem="{Binding SelectedItem}" ItemsSource="{Binding ItemsSource}">
        <ComboBox.ItemsPanel>
            <ItemsPanelTemplate>
                <VirtualizingStackPanel />
            </ItemsPanelTemplate>
        </ComboBox.ItemsPanel>
    </ComboBox> 
</DataTemplate>

Upvotes: 2

Nitin Purohit
Nitin Purohit

Reputation: 18580

If you have property defined in VM, then that will be loading just once when you will be instantiating it and be served as source for all the comboboxes.. not every combobox create its itemsSource.. it just consume it to generate its items.. so whether you put your itemsSource as Resource or in Datacontext is one and the same thing here.

Upvotes: 0

Related Questions