tags:

views:

9

answers:

2

Hi,

I am using a ScatterView and am currently binding to a folder so that when my app starts up some sample images are displayed, this works great.

<s:ScatterView x:Name="MainScatterView">
        <s:ScatterView.ItemTemplate>
            <DataTemplate>
                <Image Source="{Binding}"/>
            </DataTemplate>
        </s:ScatterView.ItemTemplate>
    </s:ScatterView>

I then set the binding using

 scatter.ItemsSource =
                System.IO.Directory.GetFiles(imagesPath, "*.jpg");

This works great but then when I try add further images:

Image img = new Image();
        img.Source =
            new BitmapImage(new Uri("\\Resources\\Koala.jpg", UriKind.Relative));
        scatter.Items.Add(img);

I get an InvalidOperationException: Operation not valid when ItemSource is in use.

What is the best way to handle this. Remove the binding and add the images manually on startup? I'm assuming then since the ItemSource is the same any further additions wont cause any problems? Or is there a better way to handle this since the binding method works really well.

cheers

A: 

I'm also new to Surface development, anyway what I have is remove the databinding and add the images manually via a for loop.

Yanny
A: 

This calls for a ViewModel

This type of problem, binding working well for the simple case but starting to fall down as you add scenarios, is a great indicator that it's time to use Model - View - ViewModel.

Roughly speaking, the idea is that you have a View (your XAML) and a Model (your data, in this case a set of files). But instead of directly binding the View to the Data, you add an intermediate class called the ViewModel. Your View binds to the ViewModel and your ViewModel loads itself from the Model. This gives you wiggle room to do more than simple things when loading data to be bound.

What does that mean here? It would look like:

public class MainViewModel
{
    // ObservableCollection adds databinding goodness so when you add a new file,
    // the UI automatically refreshes
    public ObservableCollection<string> Images { get; private set; }

    public MainViewModel(string path)
    {
        Images = new ObservableCollection<string>();
        Images.AddRange(Directory.GetFiles(path, "*.jpg"));
    }

    public void AddImage(string path)
    {
        Images.Add(path);
    }
}

and now in your xaml, you set your datacontext to new MainViewModel. You can do this in code behind or using a StaticResource, if you use a StaticResource you need a ctor that takes no parameters so you'll have to set your initial directory in some other way. Your binding then looks like:

<Image Source={Binding Images} />

Take a good look at the M-V-VM pattern. You'll find that it makes databinding problems like this easier and also has a host of other benefits like fewer event handlers (so fewer reference leaks), better testability, easier to work with Blend, and easier to add new types of UI technologies.

Jay