Search code examples
c#xamlwindows-phone-8windows-phone-8.1

Reach a TextBlock from a specific ListViewItem from the ListView in Windows Phone 8.1 XAML programmatically


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 ?


Solution

  • 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;
        }
    }