Tokfrans
Tokfrans

Reputation: 1959

Setting bind-values when adding ListviewItems in XAML

I'm sorry if the title is a bit, off. Did not know what to call it really. But here is my question:

I have a ListView with a custom ItemsTemplate, which has a Textblock and an Image. Both of which are set to get their data from binds.

But here is what I'm wondering:

If I want to add listviewItems from XAML:

<ListView HorizontalAlignment="Left" Width="150" ItemTemplate="{DynamicResource menuItems}" ItemsPanel="{DynamicResource menuLayout}">

<ListViewItem/> <---- Here
<ListViewItem/> <---- And here.
</ListView>

How can I set what values the textblock and image should have?

<ListViewItem "TextBlockValue = asdasdasds"/> etc

Here's the Itemtemplate

<DataTemplate x:Key="menuItems">
            <Grid Width="150" Height="35">
                <Image Height="35" Width="35" HorizontalAlignment="Left"/>
                <TextBlock Text="{Binding Path=Text}" Margin="40,0,0,0" VerticalAlignment="Center" FontSize="15" FontWeight="Light" Foreground="White"/>
            </Grid>
        </DataTemplate>

Upvotes: 0

Views: 69

Answers (1)

user2819245
user2819245

Reputation:

Simple and most flexible solution

As a first step, a class should be defined which serves as data container for all values of one ListViewItem.

public class ItemData
{
    public ImageSource ImageSource { get; set; }
    public string Text { get; set; }
}

(Technically, one could also do it also without such a custom class; however, the resulting XAML will look much more convoluted and much less readable.)

The data template with the bindings to the properties of ItemData elements could look like this:

<DataTemplate x:Key="menuItems">
    <StackPanel Width="150" Height="35" Orientation="Horizontal">
        <Image Source="{Binding Path=ImageSource}" Height="35" Width="35" />
        <TextBlock Text="{Binding Path=Text}" Margin="5,0,0,0" VerticalAlignment="Center" FontSize="15" FontWeight="Light" Foreground="White"/>
    </StackPanel>
</DataTemplate>

In the XAML of the ListView, a collection of ItemData objects will be constructed and assigned to the ListView.Items property. The ListView will create the ListViewItems accordingly.

<ListView HorizontalAlignment="Left" Width="150" ItemsPanel="{DynamicResource menuLayout}" ItemTemplate="{StaticResource menuItems}">
    <ListView.Items>
        <My:ItemData ImageSource="x:\\path\\to\\Img_1.png" Text="Alpha" />
        <My:ItemData ImageSource="x:\\path\\to\\Img_2.png" Text="Beta" />
    </ListView.Items>
</ListView>


Solution with explicit ListViewItem declarations

The question sounds like a solution with explicit declarations of ListViewItems is sought. However, this should not really be the recommended approach, as it will only lead to more convoluted XAML for achieving exactly the same result as the first solution, as demonstrated now.

In the XAML of the ListView, each ListViewItem together with the appropriate ItemData object will be constructed, and also the data template will be assigned to ListViewItem.ContentTemplate (ListView.ItemTemplate won't work here, since the ListViewItems are not created by the ListView).

<ListView HorizontalAlignment="Left" Width="150" ItemsPanel="{DynamicResource menuLayout}">
    <ListViewItem ContentTemplate="{StaticResource menuItems}">
        <ListViewItem.Content>
            <My:ItemData ImageSource="x:\\path\\to\\Img_1.png" Text="Alpha" />
        </ListViewItem.Content>
    </ListViewItem>
    <ListViewItem ContentTemplate="{StaticResource menuItems}">
        <ListViewItem.Content>
            <My:ItemData ImageSource="x:\\path\\to\\Img_2.png" Text="Beta" />
        </ListViewItem.Content>
    </ListViewItem>
</ListView>


If specifying the ContentTemplate for each single ListViewItem is not desired, a ListViewItem Style setting the ListViewItem.ContentTemplate property can be defined in the ListView's resource dictionary:

<ListView HorizontalAlignment="Left" Width="150" ItemsPanel="{DynamicResource menuLayout}">
    <ListView.Resources>
        <Style TargetType="{x:Type ListViewItem}">
            <Setter Property="ContentTemplate" Value="{StaticResource menuItems}" />
        </Style>
    </ListView.Resources>

    <ListViewItem>
        <ListViewItem.Content>
            <My:ItemData ImageSource="x:\\path\\to\\Img_1.png" Text="Alpha" />
        </ListViewItem.Content>
    </ListViewItem>
    <ListViewItem>
        <ListViewItem.Content>
            <My:ItemData ImageSource="x:\\path\\to\\Img_2.png" Text="Beta" />
        </ListViewItem.Content>
    </ListViewItem>
</ListView>

The style being defined inside the ListView's resource dictionary prevents any other ListViewItem control outside of this ListView from accidentally picking up this style.

Comparing the simplicity of the first solution with the verbosity of the second, it is obvious that explicit declarations of ListViewItems in XAML is not a recommended approach.

Upvotes: 1

Related Questions