0
<ScrollViewer Width="600" 
              Grid.Row="1" 
              PanningMode="Both" 
              extensions:TouchScrolling.IsEnabled="True" 
              HorizontalScrollBarVisibility="Visible"
              VerticalScrollBarVisibility="Disabled">

    <Grid Grid.Row="1">
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <Border Width="175" 
                Grid.Row="0" 
                Grid.Column="0">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition Height="170" />
                    <RowDefinition Height="Auto" />
                    <RowDefinition Height="Auto" />
                </Grid.RowDefinitions>

                <Grid Grid.Row="0" >
                    <Grid MinWidth="{Binding ElementName=backgroundImage, Path=ActualWidth}" >
                        <StackPanel HorizontalAlignment="Center" 
                                    Orientation="Horizontal" >
                            <Image Height="160" 
                                   Source="man.png" />
                        </StackPanel>
                    </Grid>
                </Grid>
                <TextBlock TextWrapping="Wrap"
                           Grid.Row="1" 
                           FontSize="10" 
                           Text="Bomber jacket..." />
            </Grid>
        </Border>

        <Border Width="175" 
                Grid.Row="0"
                Grid.Column="1">...
        </Border>
        <Border Width="175" 
                Grid.Row="0"
                Grid.Column="2">...
        </Border>
        <Border Width="175" 
                Grid.Row="0" 
                Grid.Column="3">...
        </Border>
    </Grid>
</ScrollViewer>

I have above xaml. In scrollViewer i have some items. I want to initialize it with data from database. How to do this?

I need to screate some ItemControl for common XAML and bind to properties. But how can i manage to bind every item in list to be binded to that ItemControl ?


I found this topic where i understand how to build same xaml for list items, but one problem is there - How to set Grid.Column for each item?

Rachel
  • 122,023
  • 59
  • 287
  • 465
demo
  • 5,376
  • 12
  • 55
  • 130
  • So why can't you use an items control, a grid or listview or listbox. What is the exact problem, because just showing us your scrollviewer doesn't help. – TYY Nov 17 '15 at 17:05
  • @TYY, please check my update - now it seems to be much more clear for me, but still one problem – demo Nov 17 '15 at 17:09
  • This question is far from clear. What _specifically_ are you trying to accomplish? Please provide [a good, _minimal_, _complete_ code example](http://stackoverflow.com/help/mcve) that clearly shows what you're trying to do. Also provide a precise, specific explanation of what that code does now, and how that's different from what you want it to do. – Peter Duniho Nov 17 '15 at 18:44

2 Answers2

3

An ItemsControl is used to draw a UI for a collection of items.

So to start with, you need your collection of items from the database.

public ObservableCollection<MyItem> MyCollection { get; set; }

To draw this using an ItemsControl, you would use XAML like this :

<ScrollViewer Height="100">
    <ItemsControl ItemsSource="{Binding MyCollection}" />
</ScrollViewer>

This will use the default UI for an ItemsControl, which is to loop through each item in the collection, and for each one render a TextBlock with the Text property displaying the .ToString() of the item.

So what actually renders is something like

<ScrollViewer>
    <StackPanel>
        <TextBlock /> <!-- DataContext is MyCollection[0] -->
        <TextBlock /> <!-- DataContext is MyCollection[1] -->
        <TextBlock /> <!-- DataContext is MyCollection[2] -->
    </StackPanel>
</ScrollViewer>

The ItemsControl lets you modify different parts of the template though.

For example, to change the <StackPanel> in the XAML above, you would set the ItemsPanel property to use a Grid instead.

<ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
        </Grid>
    </ItemsPanelTemplate>
</ItemsControl.ItemsPanel>

Or to change the TextBlock to something else, you could change the ItemTemplate

<ItemsControl.ItemTemplate>
    <DataTemplate>
        <Border Width="175" ...>
            <TextBlock Text="{Binding Name}" />
        </Border>
    </DataTemplate>
</ItemsControl.ItemTemplate>

This would make your output render something like this

<ScrollViewer>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <Border Width="175" ...> <!-- DataContext is MyCollection[0] -->
            <TextBlock Text="{Binding Name}" />
        </Border>

        <Border Width="175" ...> <!-- DataContext is MyCollection[1] -->
            <TextBlock Text="{Binding Name}" />
        </Border>

        <Border Width="175" ...> <!-- DataContext is MyCollection[2] -->
            <TextBlock Text="{Binding Name}" />
        </Border>
    </Grid>
</ScrollViewer>

To set Grid.Column, it's actually a bit trickier. An ItemsControl actually wraps each item in a <ContentPresenter> so each item in the XAML above would actually render more like this :

<ContentPresenter>
    <Border Width="175" ...> <!-- DataContext is MyCollection[0] -->
        <TextBlock Text="{Binding Name}" />
    </Border>
</ContentPresenter>

To set a property like Grid.Column, it needs to be set on the ContentPresenter that wraps each item. And that's what the ItemContainerStyle is used for.

<ItemsControl.ItemContainerStyle>
    <Style>
        <Setter Property="Grid.Column"
                Value="{Binding ColumnIndex}" />
        <Setter Property="Grid.Row"
                Value="{Binding RowIndex}" />
    </Style>
</ItemsControl.ItemContainerStyle>

So assuming you were binding to

public ObservableCollection<MyItem> MyCollection { get; set; }

and MyItem looked like this

public class MyItem
{
    public int RowIndex { get; set; }
    public int ColumnIndex { get; set; }
    public string Name { get; set; }
}

Your final XAML might look something like this

<ItemsControl ItemsSource="{Binding MyCollection}">
    <!-- ItemsPanelTemplate -->
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition />
                    <RowDefinition />
                    <RowDefinition />
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition />
                    <ColumnDefinition />
                    <ColumnDefinition />
                </Grid.ColumnDefinitions>
            </Grid>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <!-- ItemContainerStyle -->
    <ItemsControl.ItemContainerStyle>
        <Style>
            <Setter Property="Grid.Column"
                    Value="{Binding ColumnIndex}" />
            <Setter Property="Grid.Row"
                    Value="{Binding RowIndex}" />
        </Style>
    </ItemsControl.ItemContainerStyle>

    <!-- ItemTemplate -->
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Border Width="175" ...>
                <TextBlock Text="{Binding Name}" />
            </Border>
    </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

And it would render something like this :

<ScrollViewer>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <!-- DataContext is MyCollection[0] -->
        <ContentPresenter Grid.Row="{Binding RowIndex}" Grid.Column="{Binding ColumnIndex}">
            <Border Width="175" ...> 
                <TextBlock Text="{Binding Name}" />
            </Border>
        </ContentPresenter>

        <!-- DataContext is MyCollection[1] -->
        <ContentPresenter Grid.Row="{Binding RowIndex}" Grid.Column="{Binding ColumnIndex}">
            <Border Width="175" ...> 
                <TextBlock Text="{Binding Name}" />
            </Border>
        </ContentPresenter>

        <!-- DataContext is MyCollection[2] -->
        <ContentPresenter Grid.Row="{Binding RowIndex}" Grid.Column="{Binding ColumnIndex}">
            <Border Width="175" ...> 
                <TextBlock Text="{Binding Name}" />
            </Border>
        </ContentPresenter>
    </Grid>
</ScrollViewer>
Rachel
  • 122,023
  • 59
  • 287
  • 465
  • Thanks! It's very cool explanation. Just one question about `ColumnIndex` and `RowIndex` - can I somehow set it as number of item in collection? without adding property for it? – demo Nov 18 '15 at 12:08
  • Ooops, don't worry - i found solution here http://stackoverflow.com/a/30324533/3917754 seems to be good – demo Nov 18 '15 at 12:46
0

If i'm right what you mean is that you want to bind a list of items to your xaml. To do this you can use a GridView.

In a Gridview you bind a list of items and define a template for each of these items.

<GridView ItemsSource="{Binding MyList}">
                    <Gridview.ItemTemplate>
                        <DataTemplate>
                            <TextBlock Text="{Binding foo}"/>
                        </DataTemplate>
                    </GridView.ItemTemplate>

                    <GridView.ItemsPanel>
                        <ItemsPanelTemplate>
                            <WrapGrid MaximumRowsOrColumns="4" Orientation="Horizontal"/>
                        </ItemsPanelTemplate>
                    </GridView.ItemsPanel>
                </GridView>

As you can see. the gridview items template defines how each item in the list is going to be displayed. When you overwrite the itemspanel you can set MaximumRowsOrColumns and Orientation to define how many items each row will have and which way the rows are facing.

StijnvanGaal
  • 423
  • 3
  • 16