Updating row when changing property

16 posts, 0 answers
  1. Paolo
    Paolo avatar
    423 posts
    Member since:
    Jun 2009

    Posted 30 Sep 2011 Link to this post

    Hello,
    I'm new to winforms, I've used silverlight a lot in last 2 years... I was wondering why a simple thing I do in SL it seems to me so complicated here. ..

    I got a class defined as

    public class RapportoItem : INotifyPropertyChanged
      {
          private int _Thread;
     
          public int Thread
          {
              get
              {
                  return _Thread;
              }
              set
              {
                  _Thread = value;
                  NotifyPropertyChanged("Thread");
              }
          }
     
          public int RetryCount { get; set; }
     
          public event PropertyChangedEventHandler PropertyChanged;
     
          private void NotifyPropertyChanged(String info)
          {
              if (PropertyChanged != null)
              {
                  PropertyChanged(this, new PropertyChangedEventArgs(info));
              }
          }
      }

    And a
    Telerik.WinControls.Data.ObservableCollection<RapportoItem> result = ...

    that's bound to the RadGridView using
    radGridView1.DataSource= result;

    Why when I update the Thread element it's not refreshed in the grid?
    Thanks

    Paolo
  2. Emanuel Varga
    Emanuel Varga avatar
    1336 posts
    Member since:
    May 2010

    Posted 30 Sep 2011 Link to this post

    Hello Paolo,

    Welcome to winforms :p.

    Please try using a BindingList<T> and tell me if you see the same behavior.

    Hope this helps, if you have any other questions or comments, please let me know,

    Best Regards,
    Emanuel Varga

    Telerik WinForms MVP
  3. UI for WinForms is Visual Studio 2017 Ready
  4. Paolo
    Paolo avatar
    423 posts
    Member since:
    Jun 2009

    Posted 30 Sep 2011 Link to this post

    Hello Emanuel,
    It's not updating.... the

    private void NotifyPropertyChanged(String info)
          {
              if (PropertyChanged != null) //is null here
              {
                  PropertyChanged(this, new PropertyChangedEventArgs(info));
              }
          }

    PropertyChanged is null...
  5. Emanuel Varga
    Emanuel Varga avatar
    1336 posts
    Member since:
    May 2010

    Posted 30 Sep 2011 Link to this post

    Hello Paolo,

    Please try this:

    using System;
    using System.ComponentModel;
    using System.Windows.Forms;
    using Telerik.WinControls.UI;
     
    public partial class Form1 : Form
    {
        private RadGridView radGridView;
        private BindingList<Person> _list;
        private Timer _updateTimer;
     
        public Form1()
        {
            InitializeComponent();
            this.Controls.Add(radGridView = new RadGridView());
            radGridView.Dock = DockStyle.Fill;
            radGridView.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill;
     
            _list = new BindingList<Person>();
            for (int i = 0; i < 10; i++)
            {
                _list.Add(new Person(i, "Person" + i));
            }
     
            radGridView.DataSource = _list;
        }
     
        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
     
            _updateTimer = new Timer();
            _updateTimer.Interval = 200;
            _updateTimer.Tick += new EventHandler(timer_Tick);
            _updateTimer.Enabled = true;
        }
     
        protected override void OnClosing(CancelEventArgs e)
        {
            base.OnClosing(e);
            if (_updateTimer != null)
            {
                _updateTimer.Dispose();
                _updateTimer = null;
            }
        }
     
        private void timer_Tick(object sender, EventArgs e)
        {
            var personIndex = new Random(DateTime.Now.Millisecond).Next(0, _list.Count);
            _list[personIndex].Name = "Person" + new Random(DateTime.Now.Millisecond).Next(0, 10000);
        }
    }
     
    public class Person : INotifyPropertyChanged
    {
        private int _id;
        private string _name;
     
        public Person(int id, string name)
        {
            Id = id;
            Name = name;
        }
     
        public event PropertyChangedEventHandler PropertyChanged;
     
        public string Name
        {
            get { return _name; }
            set { _name = value; OnPropertyChanged("Name"); }
        }
     
        public int Id
        {
            get { return _id; }
            set { _id = value; OnPropertyChanged("Id"); }
        }
     
        private void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    Hope this helps, if you have any other questions or comments, please let me know,

    Best Regards,
    Emanuel Varga

    Telerik WinForms MVP
  6. Jack
    Admin
    Jack avatar
    2333 posts

    Posted 04 Oct 2011 Link to this post

    Hello Paolo,

    Like Emanuel said, you have to use a collection which inherits from IBindingList to reflect changes in your data source automatically. One possible solution is to use the BindingList<T> collection. If this does not help, please open a support ticket and send us your application. We will investigate it and we will try to find the best option in your case.

    If you have further questions, do not hesitate to ask.
     
    Kind regards,
    Jack
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  7. Erich
    Erich avatar
    10 posts
    Member since:
    Dec 2014

    Posted 06 Jul in reply to Emanuel Varga Link to this post

    Sorry for opening this rather old post, but I stumbled upon your solution, when finding a way to solve my problem.

    My Solution, looks almost the same as your example, but the timer_Tick method gets called by another thread that the gui thread, which then causes an InvalidOperationException when altering the collecion.

    How can i change the BindingList<Person> from another thread? Using the Invoker pattern seems not right here, because I'm not specifically updating RadGridView. Moreover I'm updating its datasource.

     

    So

    if (radGridView.InvokeRequired)

    ...

    _list.Add(new Person(i, "Person" + i));

    does not work here.

     

    How can I solve this problem?

     

    Best regards

    Erich

  8. Dess
    Admin
    Dess avatar
    1609 posts

    Posted 07 Jul Link to this post

    Hello Erich,

    Thank you for writing. 

    Note that all UI controls are not thread safe controls in the whole Windows Forms platform (not just Telerik controls, but all controls out there). Here is an article on MSDN, describing how to make thread-safe Winforms UI application. This means that any control from the Telerik UI for WinForms suite is not thread safe as well and cannot be used outside the main UI thread. You should use an Invoke to update the controls in cross threading scenario.

    If you are still experiencing any further difficulties, feel free to open a support ticket providing a sample project which demonstrates the problem. Thus, we would be able to investigate the precise case and assist you further. Thank you in advance.

    I hope this information helps. Should you have further questions I would be glad to help.

    Regards,
    Dess
    Telerik by Progress
    Check out the Windows Forms project converter, which aids the conversion process from standard Windows Forms applications written in C# or VB to Telerik UI for WinForms.For more information check out this blog post and share your thoughts.
  9. Erich
    Erich avatar
    10 posts
    Member since:
    Dec 2014

    Posted 07 Jul in reply to Dess Link to this post

    I understand, that I should use Invoke to update my Control from another thread like this:

     

    01.if (this.textBox1.InvokeRequired)
    02.{  
    03.    SetTextCallback d = new SetTextCallback(SetText);
    04.    this.Invoke(d, new object[] { text });
    05.}
    06.else
    07.{
    08.    this.textBox1.Text = text;
    09.}

     

    But in my case I don't want to update the Control. I'm updating the DataSource of the control.

     

    How can I tell the gui thread to make this update?

     

    Doing it like this:

    01.if (this.listOfItems.InvokeRequired)
    02.{  
    03.    SetTextCallback d = new SetTextCallback(addItem);
    04.    this.Invoke(d, new object[] { listItem});
    05.}
    06.else
    07.{
    08.    this.listOfItems.Add(listItem);
    09.}

     

    seems very wrong. How else can I do it?

     

    I can't believe I'm the only one facing this problem? This seems so trivial, there must be hundreds of solutions out there.

  10. Dess
    Admin
    Dess avatar
    1609 posts

    Posted 07 Jul Link to this post

    Hello Erich,

    Thank you for writing back. 

    Following the explained approach in the referred articles, I have prepared a sample code snippet for your reference:
    BindingList<Student> collectionOfStudents = new BindingList<Student>();
    BackgroundWorker bw = new BackgroundWorker();
     
    public Form1()
    {
        InitializeComponent();
        collectionOfStudents.Add(new Student(0, "Peter", "A+"));
        collectionOfStudents.Add(new Student(1, "John", "D-"));
        collectionOfStudents.Add(new Student(2, "Antony", "B+"));
        collectionOfStudents.Add(new Student(3, "David", "A-"));
        collectionOfStudents.Add(new Student(4, "John", "D-"));
        this.radGridView1.DataSource = collectionOfStudents;
        bw.DoWork += bw_DoWork;
    }
     
    private void bw_DoWork(object sender, DoWorkEventArgs e)
    {
        if (this.radGridView1.InvokeRequired)
        {
            AddRecordCallback d = new AddRecordCallback(AddRecord);
            this.Invoke(d, new object[] { collectionOfStudents });
        }
        else
        {
            AddRecord(collectionOfStudents);
        }
    }
     
    private void radButton1_Click(object sender, EventArgs e)
    {
        if (!bw.IsBusy)
        {
            bw.RunWorkerAsync();
        }
    }
     
    delegate void AddRecordCallback(BindingList<Student> collection);
     
    private void AddRecord(BindingList<Student> collection)
    {
        for (int i = 0; i < 100; i++)
        {
            collection.Add(new Student(collection.Count , "Peter", "A+"));
        }
    }
     
    public class Student : System.ComponentModel.INotifyPropertyChanged
    {
        int m_id;
        string m_name;
        string m_grade;
     
        public event PropertyChangedEventHandler PropertyChanged;
     
        public Student(int m_id, string m_name, string m_grade)
        {
            this.m_id = m_id;
            this.m_name = m_name;
            this.m_grade = m_grade;
        }
     
        public int Id
        {
            get
            {
                return m_id;
            }
            set
            {
                if (this.m_id != value)
                {
                    this.m_id = value;
                    OnPropertyChanged("Id");
                }
            }
        }
     
        public string Name
        {
            get
            {
                return m_name;
            }
            set
            {
                if (this.m_name != value)
                {
                    this.m_name = value;
                    OnPropertyChanged("Name");
                }
            }
        }
     
        public string Grade
        {
            get
            {
                return m_grade;
            }
            set
            {
                if (this.m_grade != value)
                {
                    this.m_grade = value;
                    OnPropertyChanged("Grade");
                }
            }
        }
     
        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

    I hope this information helps. If you have any additional questions, please let me know.

    Regards,
    Dess
    Telerik by Progress
    Check out the Windows Forms project converter, which aids the conversion process from standard Windows Forms applications written in C# or VB to Telerik UI for WinForms.For more information check out this blog post and share your thoughts.
  11. Erich
    Erich avatar
    10 posts
    Member since:
    Dec 2014

    Posted 08 Jul in reply to Dess Link to this post

    I managed to solve the problem like this

    thank you!

  12. Erich
    Erich avatar
    10 posts
    Member since:
    Dec 2014

    Posted 08 Jul in reply to Erich Link to this post

    Now I'm facing the next problem.

    I have my gridview automatically grouped by two columns. These groups are collapsed by dafault. Now whenerver an item gets removed from my list the group where the item was in, gets expanded automatically, which is very annoying and not what i intended to do.

    On the other hand, when I add an item to the ist, this doesn't happen, which how it should be.

    How can i turn this off?

  13. Dess
    Admin
    Dess avatar
    1609 posts

    Posted 08 Jul Link to this post

    Hello Erich,

    Thank you for writing back. 

    In order to avoid expanding the row when adding/removing a record, it is necessary to set the MasterTemplate.SelectLastAddedRow property to false.

    If you are still experiencing any further difficulties, feel free to open a support ticket providing a sample project which demonstrates the problem. Thus, we would be able to investigate the precise case and assist you further. Thank you in advance.

    I hope this information helps. If you have any additional questions, please let me know.

    Regards,
    Dess
    Telerik by Progress
    Check out the Windows Forms project converter, which aids the conversion process from standard Windows Forms applications written in C# or VB to Telerik UI for WinForms.For more information check out this blog post and share your thoughts.
  14. Erich
    Erich avatar
    10 posts
    Member since:
    Dec 2014

    Posted 29 Jul in reply to Dess Link to this post

    In some random cases it still expands some groups, when there is a change in the underlying BindingList.

    The next Problem is, that the performace is terrible now. Gui is very slow when i open the view where I see this radgridview. Any Ideas on how i can fix this?

     

    I already take into consideration to use a List instead of a BindingList and then only update when an update-button is pressed. WHat function would allow me to do so?

  15. Dess
    Admin
    Dess avatar
    1609 posts

    Posted 29 Jul Link to this post

    Hello Erich,

    Thank you for writing back. 
      
    Without replicating the issue locally with the group expanding, we can make only conjectures what is causing the problem on your end. That is why we need a sample project demonstrating the issue. This would be the fastest way to make an adequate analysis of the problem and assist you further. Thank you in advance for the cooperation.

    As to the performance, if you have a large amount of data (over 200-300K rows), it may affect the performance in RadGridView. For such cases, we can offer our RadVirtualGrid which provides a convenient way to implement your own data management operations and optimizes the performance when interacting with large amounts of data. However, if you don't have a lot of rows and there is a performance problem in your grid, could you please specify the exact steps how to reproduce the performance issue or feel free to submit a support ticket and get back to me with a sample project so I can investigate the precise case? Thank you.

    I am looking forward to your reply.

    Regards,
    Dess
    Telerik by Progress
    Check out the Windows Forms project converter, which aids the conversion process from standard Windows Forms applications written in C# or VB to Telerik UI for WinForms.For more information check out this blog post and share your thoughts.
  16. Erich
    Erich avatar
    10 posts
    Member since:
    Dec 2014

    Posted 02 Aug in reply to Dess Link to this post

    I'm afraid I can't give you a sample application, because my application is too big and with too many interfaces that I can't give it to you.

    But if anyone else has a similar problem, this is what I did to have an at least acceptable solution.

    I changed the List from a BindingList to a normal List and added a "Refresh" Button.

    The command of this button, first sets the source to null and then adds the List as source again.

    This way I don't have the performance issues anymore and I don't have the problem of the expanding group.

    Furthermore I bind the command to the event of the tab page container where the list is in. So everytime the current tab page gets changed to the view with the list, I run the refresh command.

     

     

     

  17. Dess
    Admin
    Dess avatar
    1609 posts

    Posted 02 Aug Link to this post

    Hello Erich,

    Thank you for writing back. 

    I am glad that you have a suitable solution for your case. However, note that unlike the forum, our support ticketing system is a private communication channel and you should not be worried about sharing confidential information. You can be certain that it will be used only for investigation purposes of this case and your privacy will be respected. Confidentiality is also described in our product EULA - See Section 11 of the WinForms EULA and Article V Section 11 of the DevCraft Complete and DevCraft Ultimate EULAs. So, if you decide to provide a project demonstrating the performance problem, we would be glad to investigate it.

    If you have any additional questions, please let me know.

    Regards,
    Dess
    Telerik by Progress
    Check out the Windows Forms project converter, which aids the conversion process from standard Windows Forms applications written in C# or VB to Telerik UI for WinForms.For more information check out this blog post and share your thoughts.
Back to Top
UI for WinForms is Visual Studio 2017 Ready