Listbox add item makes logic not work

LexiCodes 1 Reputation point
2020-04-09T08:22:24.59+00:00

I have a listbox that has 3 items at design time, my logic works, but if I add a button that adds 100 items at run time it does NOT.
I am trying to switch the color of the selection to a different colors with a case statement.

 public int caseSwitch { get; private set; }

        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new MyViewModel(caseSwitch);

        }

        private void ListBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            this.DataContext = new MyViewModel(caseSwitch);
        }

        private void label1_MouseDown(object sender, MouseButtonEventArgs e)
        {
            caseSwitch = 1;
        }






    public class MyViewModel : INotifyPropertyChanged
    {
    public event PropertyChangedEventHandler PropertyChanged;

    Random r = new Random();
    private SolidColorBrush _scb = new SolidColorBrush();
    public SolidColorBrush Scb

    {
    get { return _scb; }
    set { _scb = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Scb")); }
    }



    public MyViewModel(int caseSwitch)
    {
    switch (caseSwitch)
    {
    case 1:
    Scb = new SolidColorBrush(Color.FromRgb((byte)r.Next(1, 255), (byte)r.Next(1, 255), (byte)r.Next(1, 233)));

    //Console.WriteLine("Case 1");
    break;

    case 2:
    Scb = new SolidColorBrush(Color.FromRgb(255, 160, 122));
    break;


    default:
    Scb = new SolidColorBrush(SystemColors.HighlightBrush.Color);
    break;

    }

    }
Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,670 questions
0 comments No comments
{count} votes

6 answers

Sort by: Most helpful
  1. Peter Fleischer (former MVP) 19,231 Reputation points
    2020-04-09T09:55:04.387+00:00

    Hi, It's not necessary to set a new ViewModel instance. In this case you must refresh the whole MainWindow. The better approach is to use the same instance and change only the property in this instance.

    Try this demo:

    XAML:

    <Window x:Class="WpfApp1.Window23"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp1"
            mc:Ignorable="d"
            Title="Window23" Height="450" Width="800">
      <StackPanel>
        <Label Content="Test" MouseDown="Label_MouseDown"  Background="{Binding Scb}"/>
        <ListBox x:Name="ListBox1" SelectionChanged="ListBox1_SelectionChanged">
          <ListBoxItem>Row 1</ListBoxItem>
          <ListBoxItem>Row 2</ListBoxItem>
          <ListBoxItem>Row 3</ListBoxItem>
        </ListBox>
      </StackPanel>
    </Window>
    

    Code:

    using System;
    using System.ComponentModel;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Media;
    
    namespace WpfApp1
    {
      /// <summary>
      /// Interaction logic for Window23.xaml
      /// </summary>
      public partial class Window23 : Window
      {
        public Window23()
        {
          InitializeComponent();
          this.DataContext = vm;
        }
    
        MyViewModel vm = new MyViewModel();
    
        private void Label_MouseDown(object sender, MouseButtonEventArgs e) => vm.CaseSwitch = 1;
    
        private void ListBox1_SelectionChanged(object sender, SelectionChangedEventArgs e) => vm.SetScb();
    
        public class MyViewModel : INotifyPropertyChanged
        {
          public event PropertyChangedEventHandler PropertyChanged;
          public int CaseSwitch { get; set; }
    
          Random r = new Random();
          private SolidColorBrush _scb = new SolidColorBrush();
          public SolidColorBrush Scb
    
          {
            get { return _scb; }
            set { _scb = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Scb")); }
          }
    
          public void SetScb()
          {
            switch (CaseSwitch)
            {
              case 1:
                Scb = new SolidColorBrush(Color.FromRgb((byte)r.Next(1, 255), (byte)r.Next(1, 255), (byte)r.Next(1, 233)));
                break;
              case 2:
                Scb = new SolidColorBrush(Color.FromRgb(255, 160, 122));
                break;
              default:
                Scb = new SolidColorBrush(SystemColors.HighlightBrush.Color);
                break;
            }
          }
        }
      }
    }
    
    0 comments No comments

  2. LexiCodes 1 Reputation point
    2020-04-09T10:36:39.687+00:00

    Hi thanks for your answer,

    But the label is bound here, the listbox item needs to be bound.

    The label should be for example red, and clicking on it and selecting the listbox item should make the listbox item red.

    The probelm i am having is the button that adds the items, stops it working.

      private void button_Click(object sender, RoutedEventArgs e)
    
                { 
    
                    for (int i = 1; i<101; i++)
                    {
    
                       listBox1.Items.Add("This is item number " + i);
                    }}
    
    0 comments No comments

  3. Peter Fleischer (former MVP) 19,231 Reputation points
    2020-04-09T11:50:03.053+00:00

    Hi, for changing background color you can use Style like in following demo:

    XAML:

    <Window x:Class="WpfApp1.Window23"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp1"
            mc:Ignorable="d"
            Title="Window23" Height="450" Width="800">
      <StackPanel>
        <Button Content="Add Item" Click="Button_Click" Margin="5"/>
        <ListBox ItemsSource="{Binding View}" Margin="5">
          <ListBox.Resources>
            <Style TargetType="{x:Type ListBoxItem}">
              <Setter Property="Template">
                <Setter.Value>
                  <ControlTemplate TargetType="{x:Type ListBoxItem}">
                    <Border x:Name="Bd"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}"
                            Background="{TemplateBinding Background}"
                            Padding="{TemplateBinding Padding}"
                            SnapsToDevicePixels="true">
                      <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                                        SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                                        VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
                    </Border>
                    <ControlTemplate.Triggers>
                      <MultiTrigger>
                        <MultiTrigger.Conditions>
                          <Condition Property="Selector.IsSelectionActive"
                                     Value="False" />
                          <Condition Property="IsSelected"
                                     Value="True" />
                        </MultiTrigger.Conditions>
                        <Setter Property="Background"
                                TargetName="Bd"
                                Value="DarkOrange" />
                      </MultiTrigger>
                      <MultiTrigger>
                        <MultiTrigger.Conditions>
                          <Condition Property="Selector.IsSelectionActive"
                                     Value="True" />
                          <Condition Property="IsSelected"
                                     Value="True" />
                        </MultiTrigger.Conditions>
                        <Setter Property="Background"
                                TargetName="Bd"
                                Value="OrangeRed" />
                      </MultiTrigger>
                    </ControlTemplate.Triggers>
                  </ControlTemplate>
                </Setter.Value>
              </Setter>
            </Style>
          </ListBox.Resources>
        </ListBox>
      </StackPanel>
    </Window>
    

    Code:

    using System.Collections.ObjectModel;
    using System.Windows;
    
    namespace WpfApp1
    {
      public partial class Window23 : Window
      {
        public Window23()
        {
          InitializeComponent();
          this.DataContext = vm;
        }
    
        MyViewModel vm = new MyViewModel();
    
        private void Button_Click(object sender, RoutedEventArgs e) => vm.AddItem();
    
        public class MyViewModel
        {
          private ObservableCollection<string> col = new ObservableCollection<string>();
          public ObservableCollection<string> View => col;
    
          private int i = 1;
          internal void AddItem() => col.Add($"This is item number {i++}");
        }
      }
    }
    

  4. LexiCodes 1 Reputation point
    2020-04-09T13:26:41.833+00:00
    <Window x:Class="WpfApplication2.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApplication2"
            mc:Ignorable="d"
            Title="MainWindow" Height="614.262" Width="525">
    
        <!--<Grid.RowDefinitions>
                <RowDefinition Height="25*"/>
                <RowDefinition Height="294*"/>
            </Grid.RowDefinitions>
            <Label x:Name="label1" Content="Label" HorizontalAlignment="Left" Margin="63,50.039,0,0" VerticalAlignment="Top" Height="86" Width="156" Grid.Row="1"/>
            <Button x:Name="button" Content="Button" HorizontalAlignment="Left" Height="57" Margin="321,79,0,0" Grid.Row="1" VerticalAlignment="Top" Width="79" Click="button_Click"/>-->
        <Window.Resources>
            <Style x:Key="_ListBoxItemStyle" TargetType="ListBoxItem">
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="ListBoxItem">
                            <Border Name="_Border"
                                     Padding="2"
                                     SnapsToDevicePixels="true">
                                <ContentPresenter />
                            </Border>
                            <ControlTemplate.Triggers>
                                <Trigger Property="IsSelected" Value="true">
                                    <Setter TargetName="_Border" Property="Background" Value="{Binding Scb}"/>
    
                                </Trigger>
                            </ControlTemplate.Triggers>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </Window.Resources>
        <Grid>
            <ListBox  SelectionChanged="ListBox1_SelectionChanged" Name="listBox1"  ItemContainerStyle="{DynamicResource _ListBoxItemStyle}" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto" HorizontalAlignment="Left" Width="272" Margin="52,119,0,145">
            <ListBoxItem >1</ListBoxItem>
            <ListBoxItem >2</ListBoxItem>
             <ListBoxItem>3</ListBoxItem>
    
            </ListBox>
            <StackPanel Margin="0,140,0,-140">
                <Label x:Name="label1"  MouseDown="label1_MouseDown" Content="" HorizontalAlignment="Left" Height="45" Margin="418,0,0,0" Width="57" Background="Red"/>
                <Label x:Name="label2" MouseDown="label2_MouseDown" Content="" HorizontalAlignment="Left" Height="45" Margin="418,0,0,0" Width="57" Background="Green"/>
                <Label x:Name="label3" MouseDown="label3_MouseDown" Content="" HorizontalAlignment="Left" Height="45" Margin="418,0,0,0" Width="57" Background="Yellow"/>
                <Label x:Name="label4" MouseDown="label4_MouseDown" Content="" HorizontalAlignment="Left" Height="45" Margin="418,0,0,0" Width="57" Background="Blue"/>
                <Label x:Name="label5" MouseDown="label5_MouseDown" Content="" HorizontalAlignment="Left" Height="45" Margin="418,0,0,0" Width="57" Background="Magenta"/>
                <Label x:Name="label6" MouseDown="label6_MouseDown" Content="" HorizontalAlignment="Left" Height="45" Margin="418,0,0,0" Width="57" Background="Cyan"/>
                <Label x:Name="label" MouseDown="label_MouseDown" Content="Random" HorizontalAlignment="Left" Height="45" Margin="418,0,0,0" Width="57"/>
                <Button x:Name="button" Content="Button" HorizontalAlignment="Left" Height="61" Margin="56,0,0,0" Width="269" Click="button_Click"/>
            </StackPanel>
        </Grid>
    </Window>
    
    
    
    
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    namespace WpfApplication2
    {
    
        public partial class MainWindow : Window
        {
            public int caseSwitch { get; private set; }
    
            public MainWindow()
            {
                InitializeComponent();
                this.DataContext = new MyViewModel(caseSwitch);
                //this.DataContext = this;
    
            }
    
            private void ListBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
            {
                this.DataContext = new MyViewModel(caseSwitch);
            }
    
            private void label1_MouseDown(object sender, MouseButtonEventArgs e)
            {
                caseSwitch = 1;
            }
    
            private void label_MouseDown(object sender, MouseButtonEventArgs e)
            {
                caseSwitch = 7;
            }
    
            private void button_Click(object sender, RoutedEventArgs e)
            {
                for (int i=1; i<101; i++)
                {
                    listBox1.Items.Add("This is item number " + i);
                }
                //InitializeComponent();
                //this.DataContext = new MyViewModel(caseSwitch);
    
            }
    
            private void label2_MouseDown(object sender, MouseButtonEventArgs e)
            {
                caseSwitch = 2;
            }
    
            private void label3_MouseDown(object sender, MouseButtonEventArgs e)
            {
                caseSwitch = 3;
            }
    
            private void label4_MouseDown(object sender, MouseButtonEventArgs e)
            {
                caseSwitch = 4;
            }
    
            private void label5_MouseDown(object sender, MouseButtonEventArgs e)
            {
                caseSwitch = 5;
    
            }
    
            private void label6_MouseDown(object sender, MouseButtonEventArgs e)
            {
                caseSwitch = 6;
            }
        }
    
        public class MyViewModel : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
    
            Random r = new Random();
            private SolidColorBrush _scb = new SolidColorBrush();
            public SolidColorBrush Scb
    
            {
                get { return _scb; }
                set { _scb = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Scb")); }
            }
    
            //public int caseSwitch { get; private set; }
    
            public MyViewModel(int caseSwitch)
            {
                switch (caseSwitch)
                {
                    case 7:
                        Scb = new SolidColorBrush(Color.FromRgb((byte)r.Next(1, 255), (byte)r.Next(1, 255), (byte)r.Next(1, 233)));
    
                        //Console.WriteLine("Case 1");
                        break;
    
                    case 1:
                        Scb = new SolidColorBrush(Color.FromRgb(255,0,0));
                        break;
    
                    case 2:
                        Scb = new SolidColorBrush(Color.FromRgb(0, 204, 153));
                        break;
                    case 3:
                        Scb = new SolidColorBrush(Color.FromRgb(255, 255, 51));
                        break;
                    case 4:
                        Scb = new SolidColorBrush(Color.FromRgb(0, 255, 0));
                        break;
                    case 5:
                        Scb = new SolidColorBrush(Color.FromRgb(255, 0, 255));
                        break;
                    case 6:
                        Scb = new SolidColorBrush(Color.FromRgb(0, 255, 255));
                        break;
                    default:
                        Scb = new SolidColorBrush(SystemColors.HighlightBrush.Color);
                        break;
    
                }
    
            }
    
    
        }
    }
    

    It functions as predicted.
    The button breaks it.
    Why?
    How to get it to work?

    0 comments No comments

  5. Peter Fleischer (former MVP) 19,231 Reputation points
    2020-04-09T16:32:21.387+00:00

    Hi, in your last posted code you use many instances of MyViewModel and in your Style the reference to Scb is broken. Try following demo. It works without problems:

    XAML:

    <Window x:Class="WpfApp1.Window24"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            xmlns:local="clr-namespace:WpfApp24"
            mc:Ignorable="d"
            Title="MainWindow" Height="614.262" Width="525" Loaded="Window_Loaded">
      <Window.Resources>
        <local:MyViewModel x:Key="vm"/>
        <Style x:Key="_ListBoxItemStyle" TargetType="ListBoxItem">
          <Setter Property="Template">
            <Setter.Value>
              <ControlTemplate TargetType="ListBoxItem">
                <Border Name="_Border"
                                      Padding="2"
                                      SnapsToDevicePixels="true">
                  <ContentPresenter />
                </Border>
                <ControlTemplate.Triggers>
                  <Trigger Property="IsSelected" Value="true">
                    <Setter TargetName="_Border" Property="Background" Value="{Binding Scb, Source={StaticResource vm}}"/>
    
                  </Trigger>
                </ControlTemplate.Triggers>
              </ControlTemplate>
            </Setter.Value>
          </Setter>
        </Style>
      </Window.Resources>
      <Grid DataContext="{StaticResource vm}">
        <ListBox  SelectionChanged="ListBox1_SelectionChanged" Name="listBox1"  ItemContainerStyle="{DynamicResource _ListBoxItemStyle}" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Auto" HorizontalAlignment="Left" Width="272" Margin="52,119,0,145">
          <ListBoxItem >1</ListBoxItem>
          <ListBoxItem >2</ListBoxItem>
          <ListBoxItem >3</ListBoxItem>
        </ListBox>
        <StackPanel Margin="0,140,0,-140">
          <Label x:Name="label1"  MouseDown="label1_MouseDown" Content="" HorizontalAlignment="Left" Height="45" Margin="418,0,0,0" Width="57" Background="Red"/>
          <Label x:Name="label2" MouseDown="label2_MouseDown" Content="" HorizontalAlignment="Left" Height="45" Margin="418,0,0,0" Width="57" Background="Green"/>
          <Label x:Name="label3" MouseDown="label3_MouseDown" Content="" HorizontalAlignment="Left" Height="45" Margin="418,0,0,0" Width="57" Background="Yellow"/>
          <Label x:Name="label4" MouseDown="label4_MouseDown" Content="" HorizontalAlignment="Left" Height="45" Margin="418,0,0,0" Width="57" Background="Blue"/>
          <Label x:Name="label5" MouseDown="label5_MouseDown" Content="" HorizontalAlignment="Left" Height="45" Margin="418,0,0,0" Width="57" Background="Magenta"/>
          <Label x:Name="label6" MouseDown="label6_MouseDown" Content="" HorizontalAlignment="Left" Height="45" Margin="418,0,0,0" Width="57" Background="Cyan"/>
          <Label x:Name="label" MouseDown="label_MouseDown" Content="Random" HorizontalAlignment="Left" Height="45" Margin="418,0,0,0" Width="57"/>
          <Button x:Name="button" Content="Button" HorizontalAlignment="Left" Height="61" Margin="56,0,0,0" Width="269" Click="button_Click"/>
        </StackPanel>
      </Grid>
    

    Code:

    using System;
    using System.ComponentModel;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Media;
    using WpfApp24;
    
    namespace WpfApp1
    {
      public partial class Window24 : Window
      {
        public Window24()
        {
          InitializeComponent();
        }
        private void Window_Loaded(object sender, RoutedEventArgs e) => vm = this.Resources["vm"] as MyViewModel;
        private MyViewModel vm;
        public int caseSwitch { get; private set; }
        private void ListBox1_SelectionChanged(object sender, SelectionChangedEventArgs e) =>
          vm.SetScb(caseSwitch);
        private void label1_MouseDown(object sender, MouseButtonEventArgs e) => caseSwitch = 1;
        private void label_MouseDown(object sender, MouseButtonEventArgs e) => caseSwitch = 7;
        private void button_Click(object sender, RoutedEventArgs e)
        {
          for (int i = 1; i < 101; i++)
          {
            listBox1.Items.Add("This is item number " + i);
          }
        }
        private void label2_MouseDown(object sender, MouseButtonEventArgs e) => caseSwitch = 2;
        private void label3_MouseDown(object sender, MouseButtonEventArgs e) => caseSwitch = 3;
        private void label4_MouseDown(object sender, MouseButtonEventArgs e) => caseSwitch = 4;
        private void label5_MouseDown(object sender, MouseButtonEventArgs e) => caseSwitch = 5;
        private void label6_MouseDown(object sender, MouseButtonEventArgs e) => caseSwitch = 6;
      }
    }
    namespace WpfApp24
    {
      public class MyViewModel : INotifyPropertyChanged
      {
        public event PropertyChangedEventHandler PropertyChanged;
        Random r = new Random();
        private SolidColorBrush _scb = new SolidColorBrush();
        public SolidColorBrush Scb
        {
          get { return _scb; }
          set { _scb = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Scb")); }
        }
        public void SetScb(int caseSwitch)
        {
          switch (caseSwitch)
          {
            case 7:
              Scb = new SolidColorBrush(Color.FromRgb((byte)r.Next(1, 255), (byte)r.Next(1, 255), (byte)r.Next(1, 233)));
              break;
            case 1:
              Scb = new SolidColorBrush(Color.FromRgb(255, 0, 0));
              break;
            case 2:
              Scb = new SolidColorBrush(Color.FromRgb(0, 204, 153));
              break;
            case 3:
              Scb = new SolidColorBrush(Color.FromRgb(255, 255, 51));
              break;
            case 4:
              Scb = new SolidColorBrush(Color.FromRgb(0, 255, 0));
              break;
            case 5:
              Scb = new SolidColorBrush(Color.FromRgb(255, 0, 255));
              break;
            case 6:
              Scb = new SolidColorBrush(Color.FromRgb(0, 255, 255));
              break;
            default:
              Scb = new SolidColorBrush(SystemColors.HighlightBrush.Color);
              break;
          }
        }
      }
    }
    
    0 comments No comments