newman
newman

Reputation: 6911

Where is WPF DataGrid DataBindingComplete event?

I need to take some action (e.g. make some cells readonly based on some other cells) after data biinding is completed. In WinForm DataGridView, I used to do it in DataBindingComplete event. However, I couldn't find such an event in WPF DataGrid. What else can I use?

Upvotes: 5

Views: 11142

Answers (6)

Aleksandar
Aleksandar

Reputation: 4146

I wanted to color my rows depending on their property values, and I tried a lot of events (DataGrid.Initialized, DataContextChanged, AddingNewItem, RowLoaded etc.) along with the BeginInvoke thing, but nothing worked. Then i found:

Loaded

This event did the trick, as it allowed me to iterate through my rows and color them as I wanted.

private void SubjectsList_Loaded(object sender, RoutedEventArgs e)
{
    Dispatcher.BeginInvoke(DispatcherPriority.Render, new Action(() => ColorMyRows()));
}

The CollorMyRows looks pretty similar to tihs:

private void ColorMyRows()
{
    DataGridRow row = null;
    for (int i = 0; i < SubjectsList.Items.Count; i++)
    {
        // get one row
        row = SubjectsList.ItemContainerGenerator.ContainerFromIndex(i) as DataGridRow;
        if (myConditionIsFulfilled)
        {
            row.Background = Brushes.PaleGoldenrod; // black'n gold baby
            row.ToolTip = "This item fulfills the condition.";
        }
        else
        {
            row.Background = Brushes.PaleGreen;
            row.ToolTip = "This item does not.";
        }
    }
}

Note: If You have an ObservableCollection bound to a DataGrid, the index in the loop (index of a DataGrid's row) will correspond to the index in the collection :)

Upvotes: 2

Eng.Emad Addeen
Eng.Emad Addeen

Reputation: 1

You can declare a BackgroundWorker and try to fill your GridView in the DoWork event and write your code in the RunWorkerCompleted event

Upvotes: 0

Muhammad Alaa
Muhammad Alaa

Reputation: 618

you can bind cells readonly property to a property that changes when other properties of the model changes. I was thinking exactly like you while ago, but I started to think more in the model more than the view I am not interested in DataGrid but the list that is bounded to, you can do the same I used it before in a similar situation

public class Model : INotifyPropertyChanged
    {
public bool IsChecked
        {
            get { return isChecked; }
            set
            {
                isChecked = value;
                RaisePropertyChanged("IsChecked");
                RaisePropertyChanged("Visibilty");
            }
        }
public Visibility Visibilty
        {
            get
            {
                return IsChecked ? Visibility.Visible : Visibility.Hidden;
            }
        }
}

it was a checkbox in datagrid bound to IsChecked Property and other cells bounded to visibility and it worked for me. hope this help you.

Upvotes: 0

Muhammad Alaa
Muhammad Alaa

Reputation: 618

May be you are using threads and datagrid is not thread-safe as all UI components.

Upvotes: 1

newman
newman

Reputation: 6911

This is what I figured out: DataContextChanged event is the right event to use. The only problem is that the datagrid is not quite ready to be consumed in my code inside this event. However, it works fine if I use Dispatcher.BeginInvoke like this:

Dispatcher.BeginInvoke(DispatcherPriority.Render, new Action(() => DoSomethingWithGrid()));

Can anybody explain why this is necessary?

Actually, when dealing with WPF DataGrid, I had to use Dispatcher in quite a few cases in order to make it work. Why?

Upvotes: 8

Chris Holmes
Chris Holmes

Reputation: 11574

DataContextChanged.

Upvotes: 1

Related Questions