Search code examples
c#wpfxamlwpfdatagrid

DataGrid doesn't get updated after updating ObservableCollection that's bound to it


I have a pretty serious problem for a few days that I can't solve.

I have a XAML window with a datagrid which ItemsSource is bound to a static property of a custom type that contains an ObservableCollection of another custom type.

XAML:

<Window x:Class="TheFaceBook.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:TheProject"
    Title="MainWindow" MinHeight="253" MinWidth="882" xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit" mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" d:DesignHeight="632" d:DesignWidth="933" SizeToContent="WidthAndHeight">
<Window.Resources>
    <local:MainWindow x:Key="mainWindow"/>
</Window.Resources>
<Grid>
    <Button Content="Start" Height="33" Margin="0,28,12,0" VerticalAlignment="Top" Click="BtnStart_Click" HorizontalAlignment="Right" Width="97" />
    <DataGrid Margin="12,110,12,42" AutoGenerateColumns="False" ItemsSource="{Binding CurrentUser.TaggedImages}"  >
        <DataGrid.Columns>
            <DataGridTemplateColumn Width="50" IsReadOnly="True">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <Image Source="{Binding AbsoluteURL}" />
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTextColumn Binding="{Binding FacebookURL}"/>
        </DataGrid.Columns>
    </DataGrid>
</Grid>

code behind property:

private static User m_CurrentUser;
public static User CurrentUser
{
    get { return MainWindow.m_CurrentUser; }
    set
    {
        MainWindow.m_CurrentUser = value;
    }
}

user class:

private ObservableCollection <Picture> m_TaggedImages;

#endregion
#region Properties

public ObservableCollection<Picture> TaggedImages
{
    get { return m_TaggedImages; }
    set 
    { 
        m_TaggedImages = value;
    }
}

picture class:

public class Picture : INotifyPropertyChanged
{

    #region INotifyPropertyChanged Members

    public event PropertyChangedEventHandler PropertyChanged;

    #endregion
    private string m_URL;
    private string m_AbsoluteURL;
    private List<User> m_TaggedUsers;

    public List<User> TaggedUsers
    {
        get { return m_TaggedUsers; }
        set 
        {
            m_TaggedUsers = value;
            OnPropertyChanged("TaggedUsers");
        }
    }

    public string AbsoluteURL
    {
        get { return m_AbsoluteURL; }
        set
        {
            m_AbsoluteURL = value;
            OnPropertyChanged("AbsoluteURL");
        }
    }

    public string URL
    {
        get { return m_URL; }
        set
        {
            m_URL = value;
            OnPropertyChanged("URL");
        }
    }
}

the code who adds a picture to the TaggedImagse:

inside the bgwDoWork:

bgwPictureFinder.ReportProgress(0, pic);

bgwProgressChanged:

static void bgwPictureFinder_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    if (e.ProgressPercentage == 0)
    {
        Picture pic = (Picture)e.UserState;
        MainWindow.CurrentUser.TaggedImages.Add(pic);
    }
}

when I add to the MainWindow.CurrentUser.TaggedImages manually from some other backgroundworker it is working great, but when adding from bgwPictureFinder_ProgressChanged it adds the picture to the MainWindow.CurrentUser.TaggedImages observableCollection but not updating the UI to show the image.

I just can't figure it out what is causing this problem.


Solution

  • I think you miss that on your code exemple:

    protected void OnPropertyChanged(string propertyName)
    {
       var handlers = PropertyChanged;
       if (handlers != null)
       {
          handlers(this, new PropertyChangedEventArgs(propertyName));
       }
    }
    

    And for your Binding, I use the Two Way Mode:

    {Binding..., Mode=TwoWay}