6
votes

I am a new developer on Windows Phone 8.1, I am try to reach a specific ListView item from the ListView collection and be able to color it or color the TextBock inside of it, But I can't reach the item or reach any of items inside of ListView, Please take a look for my below code :

    protected async override void OnNavigatedTo(NavigationEventArgs e)
    {
                   SQLiteRT db1 = new SQLiteRT();
            var db_connection = await db1.Connection("MyDB.sqlite");

            List<MyTBL> t_list = db1.GetTable("SELECT * FROM MyTBL LIMIT 4 ORDER BY RANDOM() ;");
            db_connection.Close();

          LV_Options.ItemsSource = t_list;
    }
 // my List View called LV_Options
private void LV_Options_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
     ListView lv1 = sender as ListView;
     if (lv1 == null)
          return;

     MyTBL wrd = lv1.SelectedItem as MyTBL;
     if (wrd == null)
         return;

     TextBlock tb = lv1.FindName("TB_AMean1") as TextBlock;
     tb.FontSize = 17; // here I got debug error (it not worked !!!!!!!)

     var item =  LV_Options.Items.ElementAt(3); // this seems not work also !!!!
     item.BackColor = Color.LightSteelBlue; 

}

As you can see above, I tried to reach a specific item by LV_Options.Items.ElementAt(3) but it doesn't work! I also tried to reach the TextBlock from the selected List view item, but also not worked !

(Updated) XAML code :

<!-- Title Panel -->
        <StackPanel Grid.Row="0" Margin="19,0,0,0">
            <TextBlock Name="TB_Rslt" Text="Here result of your answer" Style="{ThemeResource TitleTextBlockStyle}" Margin="0,12,0,0"/>
            <TextBlock Text="page title" Margin="0,-6.5,0,26.5" Style="{ThemeResource HeaderTextBlockStyle}" CharacterSpacing="{ThemeResource PivotHeaderItemCharacterSpacing}"/>
        </StackPanel>

        <!--TODO: Content should be placed within the following grid-->
        <Grid Grid.Row="1" x:Name="ContentRoot" Margin="19,10,19,15">
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto"/>
                <RowDefinition Height="*"/>
            </Grid.RowDefinitions>
            <TextBlock Name="TB_Question" Text="Choose Answer " Margin="0,0,25,0" HorizontalAlignment="Right" FontWeight="Bold" FontSize="22" FontFamily="Verdana" RenderTransformOrigin="0.5,0.5" />
            <TextBlock Name="TB_EnWord" Text="" Margin="90,0,15,0" HorizontalAlignment="Left" FontWeight="Bold" FontSize="22" FontFamily="Verdana" RenderTransformOrigin="0.5,0.5" TextAlignment="Right" />
            <StackPanel Grid.Row="1" Margin="5,22,0,0">
                <ListView Name="LV_Options" SelectionChanged="LV_Options_SelectionChanged">
                    <ListView.ItemTemplate>
                        <DataTemplate>
                            <Grid Margin="6">
                       <StackPanel VerticalAlignment="Top" Margin="10,0,0,0">
                 <TextBlock Name="TB_AMean1" Text="{Binding AMean1}" TextWrapping="Wrap"/>
                                </StackPanel>
                            </Grid>
                        </DataTemplate>
                    </ListView.ItemTemplate>

                </ListView>
            </StackPanel>
            <Button Name="Btn_Answer" Content="Ansewr" HorizontalAlignment="Left" Grid.Row="1" VerticalAlignment="Bottom" Click="Btn_Answer_Click"/>

My application is a quiz application that offer 4 choices/options as answers for each question, and when user select a true answer, I want to highlight the true answer(true choice) by make its background to green, and if the user selected wrong answer/option I want to make the background of that answer (a specific List View item) with red.

Any help please ?

2
You need to populate your ItemsSource with an Observable Collection with the property you want to change. It won't change unless you raise the INofityEvent.Chubosaurus Software
See stackoverflow.com/questions/25070203/… for an example of Observable Collection and back ground highlighting.Chubosaurus Software
I want to color the right option and not only the selected option!Bashar Abu Shamaa
@BasharAbuShaman Umm, you can modify that code to do exactly what you want. I only suggest that you look it so you can understand why your UI is not updating. In your code you need to notify the ListView that an item has changed. This is not regular win32/winforms programming with an OnPaint - Refresh(), you have to play by their rules.Chubosaurus Software

2 Answers

3
votes

You're not going to be able to access an element inside a data template like that. Instead, leverage the binding to a view model to set the color and other view-related properties. First, create a wrapper view model for your data class:

public class MyTBLViewModel : INotifyPropertyChanged
{
    public MyTBL Entity
    {
        get { return _entity; }
    }
    private readonly MyTBL _entity;

    public Brush Highlight
    {
        get { return _brush; }
        set
        {
            _brush = value;
            RaisePropertyChanged("Highlight");
        }
    }
    private Brush _highlight;

    public double ItemFontSize
    {
        get { return _itemFontSize; }
        set
        {
            _itemFontSize = value;
            RaisePropertyChanged("ItemFontSize");
        }
    }
    private Brush _itemFontSize;

    public MyTBLViewModel(MyTBL entity)
    {
        _entity = entity;
        _highlight = new SolidColorBrush(Colors.Transparent);
        _itemFontSize = 12;
    }

    public event PropertyChangedEventArgs PropertyChanged;

    protected void RaisePropertyChanged(string propName)
    {
        var handler = PropertyChanged;
        if (handler != null)
            handler(this, new PropertyChangedEventArgs(propName));
    }
}

Use this as your ItemsSource:

List<MyTBLViewModel> t_list = db1.GetTable("SELECT * FROM MyTBL LIMIT 4 ORDER BY RANDOM() ;")
    .AsEnumerable().Select(entity => new MyTBLViewModel(entity)).ToList();

Now in your view, bind the view elements to "Highlight" and "ItemFontSize", and to any other properties you like:

<ListView.ItemTemplate>
    <DataTemplate>
        <Grid Margin="6" Background="{Binding Highlight}">
            <StackPanel VerticalAlignment="Top" Margin="10,0,0,0">
                <TextBlock Name="TB_AMean1" Text="{Binding Entity.AMean1}" TextWrapping="Wrap" 
                           FontSize="{Binding ItemFontSize}"/>
            </StackPanel>
        </Grid>
    </DataTemplate>
</ListView.ItemTemplate>

Finally, you can get the data item from the SelectionChangedEventArgs -- use it to update your view-related properties:

private void LV_Options_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    foreach (var item in e.AddedItems.OfType<MyTBLViewModel>())
    {
        item.Highlight = new SolidColorBrush(Color.LightSteelBlue);
        item.ItemFontSize = 17;
    }

    foreach (var item in e.RemovedItems.OfType<MyTBLViewModel>())
    {
        item.Highlight = new SolidColorBrush(Colors.Transparent);
        item.ItemFontSize = 12;
    }
}
2
votes
var item =  LV_Options.Items.ElementAt(3);

This line is incorrect. It will not return you a TextBlock. I don't know what a .BackColor is, and it should not compile. The Items property in a ListView will return you a list of ListViewItems. If you want to access the inside element from a ListViewItem, you'll need to access the ContentTemplateRoot property.

Do not use var ever. It lets you assume that you know the type, whereas if you explicitly typed the declaration you would realize you're doing it wrong.

 MyTBL wrd = lv1.SelectedItem as MyTBL;
 if (wrd == null)
     return;

 TextBlock tb = lv1.FindName("TB_AMean1") as TextBlock;

What is a MyTBL type? FindName is only available to framework DependencyObjects so I'm assuming it's a user control? You have to provide a lot more code to show us what you're doing and what you're setting the ListView's ItemsSource and ItemTemplate with and what these errors are and how you have 2 breaking debug errors at once and what the error messages are.

Comprehending runtime error messages is a huge part of being a good developer.