Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DataGrid itemsource binding not updating and binding in WPF not working

I'm unable to successfully update my WPF Datagrid when the itemsource changes programatically.

XAML

<DataGrid Name="ReaderGrid" ItemsSource="{Binding myData}" Height="Auto" Width="Auto" AutoGenerateColumns="False" CanUserAddRows="False" CanUserDeleteRows="False" CanUserResizeColumns="False" CanUserResizeRows="False" CanUserReorderColumns="False" IsReadOnly="True" GridLinesVisibility="None">
    <DataGrid.Columns>
        <DataGridTextColumn Header="Count" Width="*" FontSize="14" Binding="{Binding count}" />
        <DataGridTextColumn Header="Total" Width="*" FontSize="14" Binding="{Binding total}" />
    </DataGrid.Columns>
</DataGrid>

XAML.CS(code-behind)

public partial class MainWindow : Window
{
    public ObservableCollection<obj> myData { get; set; }

    public MainWindow()
    {
        InitializeComponent();

        myData = new ObservableCollection<obj>();
        InitializeMyData();

The last function (InitializeMyData()) just fills myData with test information.

And finally object is just some test class

public class obj
{
    public int count { get; set; }
    public double total { get; set; }
}

The code AS-IS doesn't work, there are no errors except that my datagrid in WPF is empty - the only way I found to fix this is to add the following in-code after I initialize data

ReaderGrid.ItemsSource = myData;

Now all my initial data is shown, except that at any point in time after this if I change myData I would hope/expect the changes to reflect automatically in my WPF Datagrid, sadly nothing is ever updated...

Question - why is my WPF binding not working (why do I need to explicitly set in the code-behind the ItemSource), and why are changes to the myData not updating my Datagrid?

Thanks,

like image 658
JSchwartz Avatar asked Oct 15 '16 03:10

JSchwartz


1 Answers

A binding like

ItemsSource="{Binding myData}" 

does not explicitly define the source object of the binding, but only the source property. It requires that the DataContext of the binding target is set, which is then used as source object.

The DataContext is inherited from parent to child elements, and often set in a window's constructor like shown below.

Here it is the MainWindow instance, because the class MainWindow owns the source property, but typically it would be an instance of a view model class that declares the binding source properties (and also implements the INotifyPropertyChanged interface to notify about property value changes).

public ObservableCollection<obj> myData { get; } = new ObservableCollection<obj>();

public MainWindow()
{
    InitializeComponent();
    InitializeMyData();

    DataContext = this;
}

Please note also that according to widely accepted coding conventions, a C# property name starts with an uppercase letter, so your property should better be named MyData.


For your second problem, the data that isn't updating, your data item class would have to implement the INotifyPropertyChanged interface, like:

public class obj : INotifyPropertyChanged 
{
    public event PropertyChanged;

    private int _count;
    public int Count
    {
        get { return _count; }
        set
        {
            _count = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Count"));
        }
    }
}

For all the details of WPF data binding, please refer to the Data Binding Overview article on MSDN.

like image 134
Clemens Avatar answered Oct 22 '22 23:10

Clemens