locked
Which control creates a Flow Layout in LS? RRS feed

  • Question

  • I'm trying to reproduce a flow layout in LS, I have tryed several Custom Controls in the SL Framework but any of them was useful..

    Which control is the right one to create flow layout, I'm trying to create a PhotGallery-like view, the user can Snapshot pictures and they populate the Grid vertically, but there´s a lot of lost space to the right, so I want to fill the Rows until there´s no more space and continue with the next one.. 

    I think my explanation it's very precise to help you to help me :D

    Tnx


    SebaXOR

    Thursday, July 26, 2012 10:16 AM

Answers

  • If you wrap it in a UserControl and add the control to your screen bound to a collection, it's not terribly hard to do. This worked for me:

    <UserControl x:Class="SilverlightClassLibrary1.ImageListBox"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"
        xmlns:local="clr-namespace:SilverlightClassLibrary1">
        <UserControl.Resources>
            <local:ByteArrayToImageConverter x:Key="ByteArrayToImageConverter"/>
        </UserControl.Resources>
        <ListBox
            ItemsSource="{Binding Value}"
            ScrollViewer.VerticalScrollBarVisibility="Disabled">
            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <toolkit:WrapPanel
                        Orientation="Vertical"
                        ItemHeight="150"
                        ItemWidth="150"/>
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Image
                        Source="{Binding Image, Converter={StaticResource ByteArrayToImageConverter}}"
                        Stretch="Uniform"/>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </UserControl>

    ByteArrayToImageConverter that I created that takes a byte array and returns a WriteableBitmap based on it. The only two things in this that are specific to LightSwitch are the binding for the ItemsSource property and the Source property. Controls bind to the Value property of their data context to get the value that the control is bound to. In this case, Value is a VisualCollection of the entity type that I used. The Source property is bound to the Image property I have on my entity.


    Justin Anderson, LightSwitch Development Team

    • Marked as answer by sebaxor Monday, July 30, 2012 9:58 AM
    Monday, July 30, 2012 9:02 AM
    Moderator
  • Well I found a solution :)

    The binding collection for the control is named Capturas.

    The Silverlight control name is WrapLayout

    This is the code I used in the Screen (The Screen name is CrearHsitoria)

    partial void CapturasDeleteSelected_Execute()
            {
                if (wrap.InnerListBox.SelectedItems.Count == 0)
                    return;
                //Let's create a temp array for mapping the objects
                Captura[] mappedTemp = new Captura[wrap.InnerListBox.SelectedItems.Count];
                wrap.InnerListBox.SelectedItems.CopyTo(mappedTemp,0);
    
                //Let's loop the array.
                //We don't use the SelectedItems because when we delete an Item, the collection
                //is changed causing and Exception
                foreach (Captura item in mappedTemp)
                    item.Delete();
                
    
            }
    
            partial void CrearHistoria_Activated()
            {
                
                this.FindControl("Capturas").ControlAvailable += CrearHistoria_ControlAvailable;
    
            }
    
            WrapLayout wrap = null;
            void CrearHistoria_ControlAvailable(object sender, ControlAvailableEventArgs e)
            {
                wrap = (WrapLayout)e.Control;
    
            }

    The only thing I made inside the control is create a Public Property of type ListBox named "InnerListBox", then in the constructor I set the reference of the inner ListBox to that Property.. and that's it.

    I use just capture the control reference inside the ControlAvialable event, and cast it to WrapLayou, this way I can use the InnerListBox property to access the SelectedItems property and process it as I want :D

    Tanks


    SebaXOR

    • Marked as answer by sebaxor Monday, July 30, 2012 11:51 AM
    Monday, July 30, 2012 11:51 AM

All replies

  • Which control is the right one to create flow layout, I'm trying to create a PhotGallery-like view, the user can Snapshot pictures and they populate the Grid vertically, but there´s a lot of lost space to the right, so I want to fill the Rows until there´s no more space and continue with the next one..

    What I think you are looking for is the WrapPanel control from the Silverlight Toolkit and set its Orientation to Vertical.

    Justin Anderson, LightSwitch Development Team

    Thursday, July 26, 2012 8:32 PM
    Moderator
  • It can easly be used in LS via CustomControl and it automatically binds the Data as a Grid? or I have to create some Wrapper control to embed it?

    SebaXOR

    Friday, July 27, 2012 12:53 PM
  • Easily is a relative term depending on your expertise in Silverlight, XAML, and data binding. Read How To: Add A Custom Control To A Screen for basic information on how to include a given control into a particular spot on a screen.

    If you want more help, you'll have to describe how you plan on using the control. My gut tells me that you'll actually want to host the WrapPanel as the items panel in a ListBox control that you add to the screen, data bind the ListBox's ItemsSource property to the collection of items, and specify a DataTemplate for the ListBox that binds to the correct information on each item and displays it correctly. This could all be done in LightSwitch without making a wrapper control, but I would think it would be easier to write a wrapper control so that you can specify most of this information in XAML instead of having to serialize information into Silverlight concepts.


    Justin Anderson, LightSwitch Development Team

    Monday, July 30, 2012 6:44 AM
    Moderator
  • This is the situation.. I manually arrange it in paint to ilustrate it better

    I tryed to insert the custom control binding the Collection of Entities that encapsulates the Pictures but It did not show anything :(

    I have tryed creating a Wrapper Control unsuccessfully trying to set a ListBox an ItemTemplatePanel containing the WrapPanel.. 

    So, I finally ask.. how can I do that.

    Tnx


    SebaXOR

    Monday, July 30, 2012 8:30 AM
  • If you wrap it in a UserControl and add the control to your screen bound to a collection, it's not terribly hard to do. This worked for me:

    <UserControl x:Class="SilverlightClassLibrary1.ImageListBox"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit"
        xmlns:local="clr-namespace:SilverlightClassLibrary1">
        <UserControl.Resources>
            <local:ByteArrayToImageConverter x:Key="ByteArrayToImageConverter"/>
        </UserControl.Resources>
        <ListBox
            ItemsSource="{Binding Value}"
            ScrollViewer.VerticalScrollBarVisibility="Disabled">
            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <toolkit:WrapPanel
                        Orientation="Vertical"
                        ItemHeight="150"
                        ItemWidth="150"/>
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>
            <ListBox.ItemTemplate>
                <DataTemplate>
                    <Image
                        Source="{Binding Image, Converter={StaticResource ByteArrayToImageConverter}}"
                        Stretch="Uniform"/>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </UserControl>

    ByteArrayToImageConverter that I created that takes a byte array and returns a WriteableBitmap based on it. The only two things in this that are specific to LightSwitch are the binding for the ItemsSource property and the Source property. Controls bind to the Value property of their data context to get the value that the control is bound to. In this case, Value is a VisualCollection of the entity type that I used. The Source property is bound to the Image property I have on my entity.


    Justin Anderson, LightSwitch Development Team

    • Marked as answer by sebaxor Monday, July 30, 2012 9:58 AM
    Monday, July 30, 2012 9:02 AM
    Moderator
  • :D Great, I needed it Horizontally so I just change it as I need it, but it works perfectly.

    Thank you very much :D


    SebaXOR

    Monday, July 30, 2012 9:58 AM
  • Well it showed up excellent.. but now I have another problem, when deleting or editing the items, the only one affected is the last one.. so the SelectedItem internal event is not being fired.. how can I make my Wrapped control to fire it?

    I Google it a little.. and I found a little weird solution.. I think it's a little complicated and very coupled.. 

    http://blogs.microsoft.co.il/blogs/dorong/archive/2011/11/14/lightswitch-and-silverlight-passing-parameters-to-a-screen.aspx

    It's there a simplier way to do it? 

    This solution applies completely to my problem? (Considering that I only need to delete the selected item)

    Can it be extendible to a multiselect option? (I have alredy set teh SelectionMode to Multiple.. but how to make the whole interaction?)

    Tnx again :)


    SebaXOR

    Monday, July 30, 2012 10:17 AM
  • I think the problem is that the SelectedItem of the ListBox is not bound to the SelectedItem of the visual collection. Should be something like:

    <ListBox
        ItemsSource="{Binding Value}"
        SelectedItem="{Binding Value.SelectedItem, Mode=TwoWay}"
        ScrollViewer.VerticalScrollBarVisibility="Disabled">
        ...
    </ListBox>


    Justin Anderson, LightSwitch Development Team

    Monday, July 30, 2012 10:25 AM
    Moderator
  • Excellent it works for one perfectly...

    The next question is more general.. I don't know if I should create another thread?

    How can I make it for Multiple selections? and can LS natively suppor multiselection with Grids, Listboxes and all the collections controls?

    Tnx again 


    SebaXOR

    Monday, July 30, 2012 11:08 AM
  • Well I found a solution :)

    The binding collection for the control is named Capturas.

    The Silverlight control name is WrapLayout

    This is the code I used in the Screen (The Screen name is CrearHsitoria)

    partial void CapturasDeleteSelected_Execute()
            {
                if (wrap.InnerListBox.SelectedItems.Count == 0)
                    return;
                //Let's create a temp array for mapping the objects
                Captura[] mappedTemp = new Captura[wrap.InnerListBox.SelectedItems.Count];
                wrap.InnerListBox.SelectedItems.CopyTo(mappedTemp,0);
    
                //Let's loop the array.
                //We don't use the SelectedItems because when we delete an Item, the collection
                //is changed causing and Exception
                foreach (Captura item in mappedTemp)
                    item.Delete();
                
    
            }
    
            partial void CrearHistoria_Activated()
            {
                
                this.FindControl("Capturas").ControlAvailable += CrearHistoria_ControlAvailable;
    
            }
    
            WrapLayout wrap = null;
            void CrearHistoria_ControlAvailable(object sender, ControlAvailableEventArgs e)
            {
                wrap = (WrapLayout)e.Control;
    
            }

    The only thing I made inside the control is create a Public Property of type ListBox named "InnerListBox", then in the constructor I set the reference of the inner ListBox to that Property.. and that's it.

    I use just capture the control reference inside the ControlAvialable event, and cast it to WrapLayou, this way I can use the InnerListBox property to access the SelectedItems property and process it as I want :D

    Tanks


    SebaXOR

    • Marked as answer by sebaxor Monday, July 30, 2012 11:51 AM
    Monday, July 30, 2012 11:51 AM