views:

194

answers:

3

Hello, I am a seasoned C and Java programmer, but an absolute WPF newbie.

I am creating a kiosk application that will display a list of images of products that the user will click to see product details and maybe place an order.

I am trying to structure my app with MVVM Foundation because I am used to the benefits of structure and tests.

I wonder what is the most natural way to create a grid of clickable images that will fill the screen left to right, top to bottom (or the other way round, I have no exact requirements).

Any image should be bound to an object that will become current and be displayed in the next screen. Thanks for your help.

+1  A: 

In ViewModel add ObservableList<ClickableImage> m_Images as public property. In XAML use ListView for displaying ClickableImage. Create datatemplate for ClickableImage with Image and raised command uppon click.

On the XAML:

<Button Command="{Binding Path=OnClickCommand}"/>  

On the ViewModel:

public ICommand OnClickCommand {
    get
    {
        return  new RelayCommand(aram => this.Click(), param => this.CanClick);
    }
}
public void Click() {
        //i was clicked!  
        globalBigImageViewModel.BigImageContent = m_Image;
}
0xDEAD BEEF
Aha, thank you, The last point is very interesting but still escapes me: how can I raise a command on a click? I am using transparent buttons over images because I could not find how to do it.
mico
Thank you. I think I created a satisfactory clickable-image here http://stackoverflow.com/questions/2720463/creating-a-clickable-image-in-wpf.The question still open is how do I populate a grid of controls from a List
mico
+3  A: 

OK! Listen up! Here is how you do that! :) 1) Use ItemsControl together with UniformGrid to get automatic aligment

<ItemsControl>
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid>
            </UniformGrid>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <Button Width="50" Height="50"/>
    <Button Width="50" Height="50"/>
    <Button Width="50" Height="50"/>
</ItemsControl>

2) Populate ItemsControl with data from your viewmodel

<ItemsControl ItemsSource="{Binding Path=ImageList}"...

public ObservableCollection<ClickableImage> ImageList
{
    get { return m_ImageList;}
}

... constructor
{
    m_ImageList = new ObservableCollection<ClickableImage>();
    m_ImageList.Add(new ClickableImage("image.png");
}

TADAAAA!

0xDEAD BEEF
Looks great! I will try it asap.
mico
Yes, this is the way to go. I still have not ironed all the wrinkles in my dynamic image list, but yes, they appear in the right order.
mico
+1  A: 

I have refined a little the code. Here is the namespace declaration

xmlns:vm="clr-namespace:TestSandbox.ViewModels"

the DataContext

<UserControl.DataContext>
    <vm:ViewModel1/>
</UserControl.DataContext>

and the uniformGrid

<ItemsControl Name="imageList" ItemsSource="{Binding Path=Products}" BorderBrush="#FFA90606" Background="#FFE70F0F">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid Margin="50">
            </UniformGrid>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <!-- The Image binding -->
            <Image Source="{Binding Path=image}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

here is the C# code in the view model

    public List<Product> Products {get; set; }

    public ViewModel1()
    {
        Products = new List<Product>();
        Products.Add(MakeProduct(@"..\images\beemovie.jpg"));
        Products.Add(MakeProduct(@"..\images\darkknight.jpg"));
        Products.Add(MakeProduct(@"..\images\matrix.jpg"));
        Products.Add(MakeProduct(@"..\images\milo.jpg"));
        Products.Add(MakeProduct(@"..\images\superhero.jpg"));
        Products.Add(MakeProduct(@"..\images\twilight.jpg"));
        Products.Add(MakeProduct(@"..\images\xfiles.jpg"));
    }

    public Product MakeProduct(string path)
    {
        return new Product(path, MakeImage(path));
    }

    public BitmapImage MakeImage(string path)
    {
        BitmapImage bmpi = new BitmapImage();
        bmpi.BeginInit();
        bmpi.UriSource = new Uri(path, UriKind.Relative);
        bmpi.EndInit();
        return bmpi;
    }
mico