Share via

Do I really need INotifyPropertyChanged?

mauede 221 Reputation points
2022-03-08T13:56:15.81+00:00

I suspect that INotifyPropertyChanged is overkill for what I would like to achieve.
I need:
to display a list of strings in a ListBox (the 5th column in the attached picture that is not working yet)
to allow the user to edit each ListBox Item and set the status of the contained string (Accepted/Rejected) through the associated CheckBox
when the button "Confirm" is clicked, to get access to the ListBox Item strings and the associated Checkbox to save to a database the strings that have "Accepted" status
The ListBox (5th column) is defined as follows:

<ListBox x:Name="AutoStrucNames" Grid.Row="5" Grid.Column="100" Height="600" Margin="80,20,0,40" Width="160" SelectionMode="Single" HorizontalAlignment="Left" Grid.ColumnSpan="10" Background="PowderBlue"
DataContext="{Binding ElementName=main}" ItemsSource="{Binding AutoNames}" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox x:Name="CheckAccepted" Margin="3" VerticalAlignment="Center" IsChecked="{Binding IsChecked, Mode=TwoWay}" />
<TextBox Text="{Binding Value, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay }"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

Questions:

  1. Do I need InotiftPropertyChanged to read the edited strings displayed by the ListBox when the Button "Confirm" is clicked?​
  2. Do I need to define the set of strings as a List<string> or as an "ObservableCollection<string>"?​

Thank you in advance
maura.monville@Stuff .com

Developer technologies | Windows Presentation Foundation
Developer technologies | C#
Developer technologies | C#

An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.


4 answers

Sort by: Most helpful
  1. Hui Liu-MSFT 48,711 Reputation points Microsoft External Staff
    2022-03-11T08:46:59.683+00:00

    You could try to refer to the example below.
    Table Code :

    CREATE TABLE [dbo].[Table]  
    (  
        [Id] INT NOT NULL PRIMARY KEY ,   
        [Name] NCHAR(10) NULL  
    )  
    

    MainWindow.xaml:

    <StackPanel>  
            <ListBox  Name="list" Height="300"  Margin="4,4,4,4"  ItemsSource="{Binding Items}"  SelectionMode="Extended">  
                <ListBox.ItemTemplate>  
                    <DataTemplate>  
                        <StackPanel Orientation="Horizontal">  
                            <CheckBox  Name="check"  Margin="3"   VerticalAlignment="Center" Click="CheckBox_Click"   IsChecked="{Binding IsChecked, Mode=TwoWay}" />  
                            <TextBox x:Name="tb" BorderThickness="0" Text="{Binding Name}" />  
                        </StackPanel>  
                    </DataTemplate>  
                </ListBox.ItemTemplate>  
            </ListBox>  
            <Button  x:Name="btn" Content="Save" Click="btn_Click"/>  
        </StackPanel>  
    

    MainWindow.xaml.cs:

    using System.Windows;  
    using System.Windows.Controls;  
    using System.ComponentModel;  
    using System.Collections.ObjectModel;  
    using System.Data.SqlClient;  
    
    namespace ListBoxWithCheckBoxTemplateDemo  
    {  
      public partial class MainWindow : Window  
      {  
        public MainWindow()  
        {  
          InitializeComponent();  
          DataContext = new ViewModel();  
        }  
        private void CheckBox_Click(object sender, RoutedEventArgs e)  
        {  
          var cb = sender as CheckBox;  
          var item = cb.DataContext;  
          list.SelectedItem = item;  
        }  
        private void btn_Click(object sender, RoutedEventArgs e)  
        {  
          string constr = @"constr ";  
          SqlConnection con = new SqlConnection(constr);  
          con.Open();  
          foreach (Data item in list.Items)  
          {  
            if (item.IsChecked == true)  
            {  
              string sqlinsert = "INSERT INTO [dbo].[Table]([Id],[Name])VALUES(@Id,@Name)";  
              SqlCommand cmd = new SqlCommand(sqlinsert, con);  
              cmd.Parameters.AddWithValue("@Name", item.Name);  
              cmd.Parameters.AddWithValue("@Id", item.Id);  
              SqlCommand cmdCount = new SqlCommand("SELECT count(*) from [dbo].[Table] WHERE Id = @Id", con);  
              cmdCount.Parameters.AddWithValue("@Id", item.Id);  
              int count = (int)cmdCount.ExecuteScalar();  
              if (count == 0)  
              {  
                cmd.ExecuteNonQuery();  
                MessageBox.Show("item saved");  
              }  
              else  
              {  
                MessageBox.Show("item exists");  
              }  
            }  
          }  
          con.Close();  
        }  
      }  
      public class ViewModel : INotifyPropertyChanged  
      {  
        public ViewModel()  
        {  
          Items = new ObservableCollection<Data>();  
          Items.Add(new Data() { Id= 1, Name = "Beijing", IsChecked = false });  
          Items.Add(new Data() { Id = 2, Name = "Shanghai", IsChecked = false });  
          Items.Add(new Data() { Id = 3, Name = "Guangdong", IsChecked = true });  
          Items.Add(new Data() { Id = 4, Name = "Beijing", IsChecked = true });  
        }  
        private ObservableCollection<Data> _items;  
        public ObservableCollection<Data> Items  
        {  
          get => _items;  
          set  
          {  
            _items = value;  
            OnPropertyChanged(nameof(Items));  
          }  
        }  
        public event PropertyChangedEventHandler PropertyChanged;  
        protected virtual void OnPropertyChanged(string propertyName)  
        {  
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));  
        }  
      }  
      public class Data  
      {  
        public int Id { get;set;}  
        public string Name { get; set; }  
        public bool IsChecked { get; set; }  
        public override string ToString() => Name;  
      }  
    }  
    

    The result:

    182128-13.gif


    If the response is helpful, please click "Accept Answer" and upvote it.
     Note: Please follow the steps in our [documentation][5] to enable e-mail notifications if you want to receive the related email notification for this thread. 

    [5]: https://learn.microsoft.com/en-us/answers/articles/67444/email-notifications.html

    Was this answer helpful?

    1 person found this answer helpful.
    0 comments No comments

  2. Karen Payne MVP 35,606 Reputation points Volunteer Moderator
    2022-03-08T17:30:21.827+00:00

    To start off, the following code is meant to be to learn from, not to match your current requirements. I use a database but the code can work without a database. So with that you may or may not want to continue, it's your choice.

    Was this answer helpful?

    1 person found this answer helpful.
    0 comments No comments

  3. mauede 221 Reputation points
    2022-03-08T16:54:53.867+00:00

    At the moment nothing is displayed in the ListBox maybe because it is filled with TextBoxes.

    <ListBox x:Name="AutoStrucNames" Grid.Row="5" Grid.Column="100" Height="600" Margin="80,20,0,40" Width="160" SelectionMode="Single" HorizontalAlignment="Left" Grid.ColumnSpan="10" Background="PowderBlue"
    DataContext="{Binding ElementName=main}" ItemsSource="{Binding AutoNames}" >
    <ListBox.ItemTemplate>
    <DataTemplate>
    <StackPanel Orientation="Horizontal">
    <CheckBox x:Name="CheckAccepted" Margin="3" VerticalAlignment="Center" IsChecked="{Binding IsChecked, Mode=TwoWay}" />
    <TextBox Text="{Binding AutoNames, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay }"/>
    </StackPanel>
    </DataTemplate>
    </ListBox.ItemTemplate>
    </ListBox>

    The strings that I have to display are in List <string> AutoNames.

    I just try to display as follows:

    AutoStrucNames.ItemsSource = (System.Collections.IEnumerable)AutoNames;

    I see only the ListBox with many empty strings with a CheckBox . I feel frustrated.

    Was this answer helpful?

    1 person found this answer helpful.
    0 comments No comments

  4. Karen Payne MVP 35,606 Reputation points Volunteer Moderator
    2022-03-08T14:53:32.073+00:00

    You need to implement INotifyPropertyChanged if you want to subscribe to notifications that a property has changed. If you don't need to you don't have to implement this interface.

    In the case of <TextBox Text="{Binding Value, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay }"/> you don't need to implement INotifyPropertyChanged. It's easy to figure out, take the property and remove notifications, run the code and inspect edited items.

    Was this answer helpful?

    1 person found this answer helpful.

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.