This is a migrated thread and some comments may be shown as answers.

Visual refresh issue when changing DataContext (DataTable) programmatically

4 Answers 297 Views
GridView
This is a migrated thread and some comments may be shown as answers.
Miguel Peixoto
Top achievements
Rank 1
Miguel Peixoto asked on 26 Nov 2010, 01:36 PM
Hi,

Hope someone can help me with this issue that I'm facing right now.

I'm trying to implement some behaviours in calculated columns (which are not Expression columns by the way). The goal is to have the last column value returned by the business layer based in the other column values. 

I'm actually setting the DataContext as a DataView (DataTable.DefaultView), but when I try to programmatically make any change to the DataContext, the last column value doesn't actually refresh (visually) until I change to another row. 

I thought that using DefaultView, and since it implements the INotifyPropertyChanged, the row being edited would be refreshed automatically. But in fact that doesn't happen in this case.

Converters and Expression columns are not exactly an option (at least I think so), since I send the grid's DataContext back to my Business layer where I set the last column value for each row.

Help would be extremely appreciated.



4 Answers, 1 is accepted

Sort by
0
Milan
Telerik team
answered on 01 Dec 2010, 10:38 AM
Hello Miguel Peixoto,

It would be really helpful if you could reveal additional details about your solution. How are the values of the calculated column generated?


All the best,
Milan
the Telerik team
Browse the videos here>> to help you get started with RadControls for WPF
0
Miguel Peixoto
Top achievements
Rank 1
answered on 02 Dec 2010, 01:37 PM
Hi Milan,

The problem was that while I was changing a certain column value, there's a special column that I want to be updated once I leave the cell edit mode. I found that using the DefaultView I couldn't get the radgrid UI to be updated.

Then I came out with this solution: creating my own table by inheriting DataTable and implementing INotifyPropertyChanged on my own DataRow. The grid's DataContext is now set to the MyTable instead of its DefaultView.

And in fact now I get the behavior I was looking for...except now I cannot insert new rows with the ShowInsertRow option !

Any ideas on how I can fix this ? I'm really trying to avoid creating a button or a context menu option for the user to be able to insert a new row...

Please let me know if you need some more details.

/// <summary>
/// Class containing a table data.
/// </summary>
public class MyTable : DataTable
{
    
    /// <summary>
    /// Determines whether the specified table is empty.
    /// </summary>
    /// <returns>
    /// <c>true</c> if the specified table is empty; otherwise, <c>false</c>.
    /// </returns>
    public bool IsEmpty()
    {
        if (this == null)
        {
            return true;
        }
 
        if (this.Rows.Count > 0)
        {
            return false;
        }
 
        return true;
    }
 
    /// <summary>
    /// Determines whether the specified obj is equal.
    /// </summary>
    /// <param name="value">The value.</param>
    /// <returns>
    /// <c>true</c> if the specified obj is equal; otherwise, <c>false</c>.
    /// </returns>
    public bool IsEqual(object value)
    {
        PfrDataTable table = (PfrDataTable)value;
 
        if (table == null)
        {
            return false;
        }
 
        if (this.Rows.Count != table.Rows.Count)
        {
            return false;
        }
 
        for (int r = 0; r < this.Rows.Count; r++)
        {
            for (int c = 0; c < this.Columns.Count; c++)
            {
                if (this.Rows[r][c] != table.Rows[r][c])
                {
                    return false;
                }
            }
        }
 
        return true;
    }
 
    #endregion
    #region Override methods
 
    /// <summary>
    /// Gets the type of the row.
    /// </summary>
    /// <returns></returns>
    protected override Type GetRowType()
    {
        return typeof(MyTableRow);
    }
 
    /// <summary>
    /// Creates a new row from an existing row.
    /// </summary>
    /// <param name="builder">A <see cref="T:System.Data.DataRowBuilder"/> object.</param>
    /// <returns>
    /// A <see cref="T:System.Data.DataRow"/> derived class.
    /// </returns>
    protected override DataRow NewRowFromBuilder(DataRowBuilder builder)
    {
        return new MyTableRow(builder);
    }
 
    #endregion
}
    
 
/// <summary>
/// Class containing a table row data.
/// </summary>
public class MyTableRow : DataRow, INotifyPropertyChanged
{
    #region Constructor
 
    /// <summary>
    /// Initializes a new instance of the <see cref="MyTableRow"/> class.
    /// </summary>
    /// <param name="rb">The Row Builder.</param>
    public MyTableRow(DataRowBuilder rb) : base(rb)
    {
        this.AddRowEventHandler();
    }
 
    #endregion
 
    #region Handlers
 
    /// <summary>
    /// Adds the row event handler.
    /// </summary>
    public void AddRowEventHandler()
    {          
        this.Table.ColumnChanged += new DataColumnChangeEventHandler(HandleColumnChanged);
    }
 
    #endregion
 
    #region Private Methods
 
    /// <summary>
    /// Handles the column changed.
    /// </summary>
    /// <param name="sender">The sender.</param>
    /// <param name="e">The <see cref="System.Data.DataColumnChangeEventArgs"/> instance containing the event data.</param>
    private void HandleColumnChanged(object sender, DataColumnChangeEventArgs e)
    {
        if (e.Row == this)
        {
            OnPropertyChanged(e.Column.ColumnName);
        }
    }
 
    #endregion
 
    #region INotifyPropertyChanged Members
 
    /// <summary>
    /// Occurs when a property value changes.
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;
 
    /// <summary>
    /// Called when [property changed].
    /// </summary>
    /// <param name="propertyName">Name of the property.</param>
    protected void OnPropertyChanged(string propertyName)
    {
        var ev = PropertyChanged;
        if (ev != null)
        {
            ev(this, new PropertyChangedEventArgs(propertyName));
        }
    }
 
    #endregion       
}
0
Milan
Telerik team
answered on 07 Dec 2010, 02:45 PM
Hi Miguel Peixoto,

You could try the following approach:

public MainWindow()
 {
     InitializeComponent();
  
    this.Bind();
  
    this.radGridView.AddingNewDataItem += new EventHandler<GridViewAddingNewEventArgs>(radGridView_AddingNewDataItem);
    this.radGridView.RowEditEnded += new EventHandler<GridViewRowEditEndedEventArgs>(radGridView_RowEditEnded);
 }
  
void radGridView_RowEditEnded(object sender, GridViewRowEditEndedEventArgs e)
{
    if (e.EditOperationType == GridViewEditOperationType.Insert)
    {
        this.myDataTable.Rows.Add(e.EditedItem as DataRow);
        this.radGridView.Rebind();
    }
}
  
void radGridView_AddingNewDataItem(object sender, GridViewAddingNewEventArgs e)
{
    e.NewObject = this.myDataTable.NewRow();
}

AddingNewdataItem should  be used since the grid does not know how to create a new DataRow. One the data is created you should used RowEditEnded event to commit the new data.


Greetings,
Milan
the Telerik team
Browse the videos here>> to help you get started with RadControls for WPF
0
Miguel Peixoto
Top achievements
Rank 1
answered on 16 Dec 2010, 11:21 AM
Hi Milan,

I've followed your approach and it worked great.

Thanks!
Tags
GridView
Asked by
Miguel Peixoto
Top achievements
Rank 1
Answers by
Milan
Telerik team
Miguel Peixoto
Top achievements
Rank 1
Share this question
or