haosmark haosmark - 3 months ago 15
C# Question

Adding items to ObservableCollection doesn't change the ListView

I can't figure out why my ListView isn't updating when I add items to an observable collection.
Here's what the UI starts as
enter image description here

And here's what it looks like after I add an item
enter image description here

For whatever reason the ListView is not picking up the work order, nor the check in date, however it does update the TechCount...

Here's the ListView code:

<ListView Grid.Row="2"
ItemsSource="{Binding LaborItems}"
SelectedItem="{Binding SelectedLaborItem}"
Margin="10,10,10,9">
<ListView.View>
<GridView>
<GridViewColumn Header="#" Width="55" DisplayMemberBinding="{Binding Labor.WorkOrderNo}"/>
<GridViewColumn Header="Date" Width="100" DisplayMemberBinding="{Binding Labor.Time.CheckIn}"/>
<GridViewColumn Header="Techs" DisplayMemberBinding="{Binding TechCount}" />
</GridView>
</ListView.View>
</ListView>


It's easier to see relevant code in a picture, so I'm doing a screen short instead of raw code
enter image description here

Line 26 is what runs when I click the + button on the UI. TechCount has a similar implementation to CheckIn, which just refers to fields within Labor.

Here's the complete viewmodel code:

public class ServiceItemsViewModel : ViewModelBase
{
public Labor Labor { get; set; }
public ObservableCollection<Labor> LaborItems { get; private set; } = new ObservableCollection<Labor>();

public ServiceItemsViewModel()
{
Labor = new Labor();
Labor.Rates = new LaborRatesDual();
AddLaborCommand = new DelegateCommand(addLabor, null);
}

public ICommand AddLaborCommand { get; private set; }

private void addLabor(object obj)
{
LaborItems.Add(Labor);
Labor = new Labor();
}

private bool canAddLabor(object arg)
{
if (Labor.Duration.Minutes < 1)
{
return false;
}

//if (AdditionalBillingRate <= 0 || AdditionalPayoutRate <= 0)
//{
// return false;
//}

return true;
}

public DateTime CheckIn
{
get { return Labor.Time.CheckIn; }
set
{
Labor.Time.CheckIn = value;
RaisePropertyChanged(nameof(Labor));
}
}
public DateTime CheckOut
{
get { return Labor.Time.CheckOut; }
set
{
Labor.Time.CheckOut = value;
RaisePropertyChanged(nameof(Labor));
((DelegateCommand)AddLaborCommand).RaiseCanExecuteChanged();
}
}
public int TechCount
{
get { return Labor.TechCount; }
set
{
Labor.TechCount = value;
RaisePropertyChanged(nameof(Labor));
}
}
public decimal InitialPayoutRate
{
get { return Labor.Rates.InitialPayoutRate; }
set
{
Labor.Rates.InitialPayoutRate = value;
RaisePropertyChanged(nameof(Labor));
//((DelegateCommand)AddLaborCommand).RaiseCanExecuteChanged();
}
}
public decimal AdditionalPayoutRate
{
get { return Labor.Rates.AdditionalPayoutRate; }
set
{
Labor.Rates.AdditionalPayoutRate = value;
RaisePropertyChanged(nameof(Labor));
//((DelegateCommand)AddLaborCommand).RaiseCanExecuteChanged();
}
}
public decimal InitialBillingRate
{
get { return Labor.Rates.InitialBillingRate; }
set
{
Labor.Rates.InitialBillingRate = value;
RaisePropertyChanged(nameof(Labor));
//((DelegateCommand)AddLaborCommand).RaiseCanExecuteChanged();
}
}
public decimal AdditionalBillingRate
{
get { return Labor.Rates.AdditionalBillingRate; }
set
{
Labor.Rates.AdditionalBillingRate = value;
RaisePropertyChanged(nameof(Labor));
//((DelegateCommand)AddLaborCommand).RaiseCanExecuteChanged();
}
}

private Labor selectedLaborItem;
public Labor SelectedLaborItem
{
get { return selectedLaborItem; }
set
{
selectedLaborItem = value;
RaisePropertyChanged(nameof(Labor));
}
}


Labor contents after I click the + button:
enter image description here

Answer

Your column bindings are wrong:

<GridViewColumn Header="#" Width="55" DisplayMemberBinding="{Binding **Labor.**WorkOrderNo}"/>
<GridViewColumn Header="Date" Width="100" DisplayMemberBinding="{Binding **Labor.**Time.CheckIn}"/>
<GridViewColumn Header="Techs" DisplayMemberBinding="{Binding TechCount}" />

See asterisked areas above.