A ResetBindings on a BindingSource of a Grid also resets ComboBox - c#

I have a DataGridView with a BindingSource of products. This products have an enum (Producer).
For the most text fields (to edit the product) below the DataGridView I have a method RefreshProduct which does a ResetBindings in the end to refresh the DataGridView. There is a ComboBox (cboProducer), too.
If I run over the _orderBs.ResetBindings(false) it will reset my cboProducer outside the DataGridView, too. Could you please help me to avoid this?
Here follows some code; maybe it is then better to understand.
public partial class SelectProducts : UserControl
{
private AutoCompleteStringCollection _productCollection;
private ProductBL _productBL;
private OrderBL _orderBL;
private SortableBindingList<ProductBE> _listProducts;
private ProductBE _selectedProduct;
private OrderBE _order;
BindingSource _orderBs = new BindingSource();
public SelectProducts()
{
InitializeComponent();
if (_productBL == null)
_productBL = new ProductBL();
if (_orderBL == null)
_orderBL = new OrderBL();
if (_productCollection == null)
_productCollection = new AutoCompleteStringCollection();
if (_order == null)
_order = new OrderBE();
if (_listProducts == null)
{
_listProducts = _order.ProductList;
_orderBs.DataSource = _order;
grdOrder.DataSource = _orderBs;
grdOrder.DataMember = "ProductList";
}
}
private void cmdGetProduct_Click(object sender, EventArgs e)
{
ProductBE product = _productBL.Load(txtProductNumber.Text);
_listProducts.Add(product);
_orderBs.ResetBindings(false);
}
private void grdOrder_SelectionChanged(object sender, EventArgs e)
{
if (grdOrder.SelectedRows.Count > 0)
{
_selectedProduct = (ProductBE)((DataGridView)(sender)).CurrentRow.DataBoundItem;
if (_selectedProduct != null)
{
txtArticleNumber.Text = _selectedProduct.Article;
txtPrice.Text = _selectedProduct.Price.ToString("C");
txtProducerNew.Text = _selectedProduct.ProducerText;
cboProducer.DataSource = Enum.GetValues(typeof(Producer));
cboProducer.SelectedItem = _selectedProduct.Producer;
}
}
}
private void txtProducerNew_Leave(object sender, EventArgs e)
{
string property = CommonMethods.GetPropertyName(() => new ProductBE().ProducerText);
RefreshProduct(((TextBoxBase)sender).Text, property);
}
private void RefreshProduct(object value, string property)
{
if (_selectedProduct != null)
{
double valueOfDouble;
if (double.TryParse(value.ToString(), out valueOfDouble))
{
value = valueOfDouble;
}
Type type = _selectedProduct.GetType();
PropertyInfo info = type.GetProperty(property);
if (info.PropertyType.BaseType == typeof(Enum))
{
value = Enum.Parse(info.PropertyType, value.ToString());
}
try
{
Convert.ChangeType(value, info.PropertyType, new CultureInfo("de-DE"));
info.SetValue(_selectedProduct, value, null);
}
catch (Exception ex)
{
throw new WrongFormatException("\"" + value.ToString() + "\" is not a valid value.", ex);
}
var produktFromList = _listProducts.Single(p => p.Position == _selectedProduct.Position);
info.SetValue(produktFromList, value, null);
_orderBs.ResetBindings(false);
}
}
private void cboProducer_SelectedIndexChanged(object sender, EventArgs e)
{
var selectedIndex = ((ComboBox)(sender)).SelectedIndex;
switch ((Producer)selectedIndex)
{
case Producer.ABC:
txtProducerNew.Text = Constants.ABC;
break;
case Producer.DEF:
txtProducerNew.Text = Constants.DEF;
break;
case Producer.GHI:
txtProducerNew.Text = Constants.GHI;
break;
case Producer.Another:
txtProducerNew.Text = String.Empty;
break;
default:
break;
}
string property = CommonMethods.GetPropertyName(() => new ProductBE().Producer);
RefreshProduct(selectedIndex, property);
}
}

I got it!
After the ResetBindings the grdOrder_SelectionChanged-Event was raised. And after the _selectedProduct was null (I do not know why yet...) the DataSource of the cboProducer was setted again.
So the solution is to set the DataSource of the cboProducer in the constructor.
Thanks for reading.

Related

C# Error when setting ListBox.DataSource = null (Possible event firing issue?)

I have searched for a while to find a fix for this and hoped that using the 'SelectionChangeCommitted' event as per this answer ( How to prevent selectedindexchanged event when DataSource is bound? ) would work but unfortunately no such luck.
Basically I want to set my Listbox.DataSource to null, although it contains two objects at the time. It seems like when I hit the line matchupListBox.Datasource = null it jumps to the _SelectedIndexChanged event and enters my other method (LoadMatchup())
If anyone could shed some light on this or advise me on how to set it to null another way (again, SelectionChangeCommitted didn't work) I'd appreciate it. Full code for my class is below:
namespace TrackerUI
{
public partial class TournamentViewerForm : Form
{
private TournamentModel tournament;
List<int> rounds = new List<int>();
List<MatchupModel> selectedMatchups = new List<MatchupModel>();
public TournamentViewerForm(TournamentModel tournamentModel)
{
InitializeComponent();
tournament = tournamentModel;
LoadFormData();
LoadRounds();
}
private void LoadFormData()
{
tournamentName.Text = tournament.TournamentName;
}
private void WireUpMatchupsList()
{
matchupListBox.DataSource = null;
matchupListBox.DataSource = selectedMatchups;
matchupListBox.DisplayMember = "DisplayName";
}
private void WireUpRoundsList()
{
roundDropDown.DataSource = null;
roundDropDown.DataSource = rounds;
}
private void LoadRounds()
{
rounds = new List<int>();
rounds.Add(1);
int currRound = 1;
foreach (List<MatchupModel> matchups in tournament.Rounds)
{
if (matchups.First().MatchupRound > currRound)
{
currRound = matchups.First().MatchupRound;
rounds.Add(currRound);
}
}
WireUpRoundsList();
}
private void roundDropDown_SelectedIndexChanged(object sender, EventArgs e)
{
LoadAllMatchups();
}
private void LoadAllMatchups()
{
int round = (int)roundDropDown.SelectedItem;
foreach (List<MatchupModel> matchups in tournament.Rounds)
{
if (matchups.First().MatchupRound == round)
{
selectedMatchups = matchups;
}
}
WireUpMatchupsList();
}
private void LoadMatchup()
{
MatchupModel m = (MatchupModel)matchupListBox.SelectedItem;
for (int i = 0; i < m.Entries.Count; i++)
{
if (i == 0)
{
if (m.Entries[0].TeamCompeting != null)
{
teamOneName.Text = m.Entries[0].TeamCompeting.TeamName;
teamOneScoreValue.Text = m.Entries[0].Score.ToString();
teamTwoName.Text = "<bye>";
teamTwoScoreValue.Text = "0";
}
else
{
teamOneName.Text = "Not yet set.";
teamOneScoreValue.Text = "";
}
}
if (i == 1)
{
if (m.Entries[0].TeamCompeting != null)
{
teamTwoName.Text = m.Entries[1].TeamCompeting.TeamName;
teamTwoScoreValue.Text = m.Entries[1].Score.ToString();
}
else
{
teamTwoName.Text = "Not yet set.";
teamTwoScoreValue.Text = "";
}
}
}
}
private void matchupListBox_SelectedIndexChanged(object sender, EventArgs e)
{
LoadMatchup();
}
}
}
Oh by the way, probably important info I almost forgot, is that it errors on the second last method on line
MatchupModel m = (MatchupModel)matchupListBox.SelectedItem;
for (int i = 0; i < m.Entries.Count; i++)
because m is now null, although SelectedItem is 2 (int for a MatchUp model) on the form.
Thanks in advance kind people.
You can leave out the matchupListBox.DataSource = null;
Try out something like this
{
private TournamentModel tournament;
BindingList<int> rounds = new BindingList<int>();
BindingList<MatchupModel> selectedMatchups = new();
public TournamentViewerForm(TournamentModel tournamentModel)
{
InitializeComponent();
tournament = tournamentModel;
WireUpLists();
LoadFormData();
LoadRounds();
}
private void WireUpLists()
{
roundDropDown.DataSource = rounds;
matchupListBox.DataSource = selectedMatchups;
matchupListBox.DisplayMember = "DisplayName";
}
private void LoadFormData()
{
TournamentName.Text = tournament.TournamentName;
}
private void LoadRounds()
{
rounds.Clear();
rounds.Add(1);
int currRound = 1;
foreach (List<MatchupModel> matchups in tournament.Rounds)
{
if (matchups.First().MatchupRound > currRound)
{
currRound = matchups.First().MatchupRound;
rounds.Add(currRound);
}
}
LoadMatchups(1);
}
private void roundDropDown_SelectedIndexChanged(object sender, EventArgs e)
{
LoadMatchups((int)roundDropDown.SelectedItem);
}
private void LoadMatchups(int round)
{
foreach (List<MatchupModel> matchups in tournament.Rounds)
{
if (matchups.First().MatchupRound == round)
{
matchupListBox.SelectedIndexChanged -= matchupListBox_SelectedIndexChanged;
selectedMatchups.Clear();
matchupListBox.SelectedIndexChanged += matchupListBox_SelectedIndexChanged;
foreach (MatchupModel m in matchups)
{
selectedMatchups.Add(m);
}
}
}
if (selectedMatchups.Count > 0)
{
LoadMatchup(selectedMatchups.First());
}
}
private void LoadMatchup()
{
MatchupModel m = (MatchupModel)matchupListBox.SelectedItem;
for (int i = 0; i < m.Entries.Count; i++)
{
if (i == 0)
{
if (m.Entries[0].TeamCompeting != null)
{
teamOneName.Text = m.Entries[0].TeamCompeting.TeamName;
teamOneScoreValue.Text = m.Entries[0].Score.ToString();
teamTwoName.Text = "<bye>";
teamTwoScoreValue.Text = "0";
}
else
{
teamOneName.Text = "Not yet set.";
teamOneScoreValue.Text = "";
}
}
if (i == 1)
{
if (m.Entries[0].TeamCompeting != null)
{
teamTwoName.Text = m.Entries[1].TeamCompeting.TeamName;
teamTwoScoreValue.Text = m.Entries[1].Score.ToString();
}
else
{
teamTwoName.Text = "Not yet set.";
teamTwoScoreValue.Text = "";
}
}
}
}
private void matchupListBox_SelectedIndexChanged(object sender, EventArgs e)
{
LoadMatchup((MatchupModel)matchupListBox.SelectedItem);
}
}
I changed the selectedMatchups global variable type from List to that of BindingList
and then disabled the matchupListSelectedIndexChanged event just before i clear the selectedMatchups from the LoadMatchups function with selectedMatchups.Clear() and then re-eanabled after enable it just again.
This is so because this line of code selectedMatchups.Clear() triggers the matchListSelectedIndexChange event to run when not appropiate

Custom TimePickerRenderer is not firing the events to update the TimeProperty

I created a custom TimePicker and the renderers to android and iphone, with the objective to allow for that be nullable. As inspiration, was used the https://xamgirl.com/clearable-datepicker-in-xamarin-forms/
But, for some reason, the event is not firing when the time is set, thats happenen only in android, and more specific, back in android 8.1.
On shared project:
public class NullableTimePicker : TimePicker
{
public NullableTimePicker()
{
Time = DateTime.Now.TimeOfDay;
NullableTime = null;
Format = #"HH\:mm";
}
public string _originalFormat = null;
public static readonly BindableProperty PlaceHolderProperty =
BindableProperty.Create(nameof(PlaceHolder), typeof(string), typeof(NullableTimePicker), " : ");
public string PlaceHolder
{
get { return (string)GetValue(PlaceHolderProperty); }
set
{
SetValue(PlaceHolderProperty, value);
}
}
public static readonly BindableProperty NullableTimeProperty =
BindableProperty.Create(nameof(NullableTime), typeof(TimeSpan?), typeof(NullableTimePicker), null, defaultBindingMode: BindingMode.TwoWay);
public TimeSpan? NullableTime
{
get { return (TimeSpan?)GetValue(NullableTimeProperty); }
set { SetValue(NullableTimeProperty, value); UpdateTime(); }
}
private void UpdateTime()
{
if (NullableTime != null)
{
if (_originalFormat != null)
{
Format = _originalFormat;
}
}
else
{
Format = PlaceHolder;
}
}
protected override void OnBindingContextChanged()
{
base.OnBindingContextChanged();
if (BindingContext != null)
{
_originalFormat = Format;
UpdateTime();
}
}
protected override void OnPropertyChanged(string propertyName = null)
{
base.OnPropertyChanged(propertyName);
if (propertyName == TimeProperty.PropertyName ||
(
propertyName == IsFocusedProperty.PropertyName &&
!IsFocused &&
(Time == DateTime.Now.TimeOfDay)))
{
AssignValue();
}
if (propertyName == NullableTimeProperty.PropertyName && NullableTime.HasValue)
{
Time = NullableTime.Value;
if (Time == DateTime.Now.TimeOfDay)
{
//this code was done because when date selected is the actual date the"DateProperty" does not raise
UpdateTime();
}
}
}
public void CleanTime()
{
NullableTime = null;
UpdateTime();
}
public void AssignValue()
{
NullableTime = Time;
UpdateTime();
}
}
On Android project:
public class NullableTimePickerRenderer : ViewRenderer<NullableTimePicker, EditText>
{
public NullableTimePickerRenderer(Context context) : base(context)
{
}
TimePickerDialog _dialog;
protected override void OnElementChanged(ElementChangedEventArgs<NullableTimePicker> e)
{
base.OnElementChanged(e);
this.SetNativeControl(new Android.Widget.EditText(Context));
if (Control == null || e.NewElement == null)
return;
this.Control.Click += OnPickerClick;
if (Element.NullableTime.HasValue)
Control.Text = DateTime.Today.Add(Element.Time).ToString(Element.Format);
else
this.Control.Text = Element.PlaceHolder;
this.Control.KeyListener = null;
this.Control.FocusChange += OnPickerFocusChange;
this.Control.Enabled = Element.IsEnabled;
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == Xamarin.Forms.TimePicker.TimeProperty.PropertyName ||
e.PropertyName == Xamarin.Forms.TimePicker.FormatProperty.PropertyName)
SetTime(Element.Time);
}
void OnPickerFocusChange(object sender, Android.Views.View.FocusChangeEventArgs e)
{
if (e.HasFocus)
{
ShowTimePicker();
}
}
protected override void Dispose(bool disposing)
{
if (Control != null)
{
this.Control.Click -= OnPickerClick;
this.Control.FocusChange -= OnPickerFocusChange;
if (_dialog != null)
{
_dialog.Hide();
_dialog.Dispose();
_dialog = null;
}
}
base.Dispose(disposing);
}
void OnPickerClick(object sender, EventArgs e)
{
ShowTimePicker();
}
void SetTime(TimeSpan time)
{
Control.Text = DateTime.Today.Add(time).ToString(Element.Format);
Element.Time = time;
}
private void ShowTimePicker()
{
CreateTimePickerDialog(this.Element.Time.Hours, this.Element.Time.Minutes);
_dialog.Show();
}
void CreateTimePickerDialog(int hours, int minutes)
{
NullableTimePicker view = Element;
_dialog = new TimePickerDialog(Context, (o, e) =>
{
view.Time = new TimeSpan(hours: e.HourOfDay, minutes: e.Minute, seconds: 0);
view.AssignValue();
((IElementController)view).SetValueFromRenderer(VisualElement.IsFocusedProperty, false);
Control.ClearFocus();
_dialog = null;
}, hours, minutes, true);
_dialog.SetButton("ok", (sender, e) =>
{
SetTime(Element.Time);
this.Element.Format = this.Element._originalFormat;
this.Element.AssignValue();
});
_dialog.SetButton2("clear", (sender, e) =>
{
this.Element.CleanTime();
Control.Text = this.Element.Format;
});
}
}
On iOS project:
public class NullableTimePickerRenderer : TimePickerRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<TimePicker> e)
{
base.OnElementChanged(e);
var timePicker = (UIDatePicker)Control.InputView;
timePicker.Locale = new NSLocale("no_nb");
if (e.NewElement != null && this.Control != null)
{
this.UpdateDoneButton();
this.AddClearButton();
this.Control.BorderStyle = UITextBorderStyle.Line;
Control.Layer.BorderColor = UIColor.LightGray.CGColor;
Control.Layer.BorderWidth = 1;
if (Device.Idiom == TargetIdiom.Tablet)
{
this.Control.Font = UIFont.SystemFontOfSize(25);
}
}
}
private void UpdateDoneButton()
{
var toolbar = (UIToolbar)Control.InputAccessoryView;
var doneBtn = toolbar.Items[1];
doneBtn.Clicked += (sender, args) =>
{
NullableTimePicker baseTimePicker = this.Element as NullableTimePicker;
if (!baseTimePicker.NullableTime.HasValue)
{
baseTimePicker.AssignValue();
}
};
}
private void AddClearButton()
{
var originalToolbar = this.Control.InputAccessoryView as UIToolbar;
if (originalToolbar != null && originalToolbar.Items.Length <= 2)
{
var clearButton = new UIBarButtonItem("clear", UIBarButtonItemStyle.Plain, ((sender, ev) =>
{
NullableTimePicker baseTimePicker = this.Element as NullableTimePicker;
this.Element.Unfocus();
this.Element.Time = DateTime.Now.TimeOfDay;
baseTimePicker.CleanTime();
}));
var newItems = new List<UIBarButtonItem>();
foreach (var item in originalToolbar.Items)
{
newItems.Add(item);
}
newItems.Insert(0, clearButton);
originalToolbar.Items = newItems.ToArray();
originalToolbar.SetNeedsDisplay();
}
}
}
This code works fine on iOS and Android version 8.1 or higher, but in lower version, this just not fire the event to set time, setting always the default time.
I'm also provided a git repo with the code, maybe, make easily understand my problem.
https://github.com/aismaniotto/Nullable24hTimePicker
Thanks for your help. After more digging on code and debugging, I realize the problem was on OkButton implementation. On Android 8, apparently, the callback from the TimePickerDialog was called before the OkButton implementation e what was there, is ignored. On the older version, the OKButton implementation was called before and, for some reason, cancel the invocation of the callback.
That way, removing the OkButton implementation, the problem was solved... remembering that on the working version, was ignored anyway. Eventually, I will commit to the repository, to be registered.
Thanks a lot.

ICollection filter error convert type

I have filter my collection
It is my code
public ICollectionView LogEntriesStoreView { get; set; }
var collection = new ObservableCollection<Service>(this._model.GetService());
this.LogEntriesStoreView = CollectionViewSource.GetDefaultView(collection);
this.LogEntriesStoreView.Filter += new FilterEventHandler(ShowOnlyBargainsFilter);
private void ShowOnlyBargainsFilter(object sender, FilterEventArgs e)
{
AuctionItem product = e.Item as AuctionItem;
if (product != null)
{
// Filter out products with price 25 or above
if (product.CurrentPrice < 25)
{
e.Accepted = true;
}
else
{
e.Accepted = false;
}
}
}
Now I get this error
Implicit type conversion "System.Windows.Data.Filter EventHandler" in "System.Predicate " can not be
this._view = new TViewType();
this._model = new ServiceModel();
this.Service = new ObservableCollection<Service>(this._model.GetService());
this.OkCommand = new RelayCommand(o => this.OKRun());
this.LostFocusCommand = new RelayCommand(o => this.LostFocusOKRun());
// в переменную получаем нашу коллекцию
var collection = new ObservableCollection<Service>(this._model.GetService());
// инициализируем поле типа ICollectionView нашей коллецией
this.LogEntriesStoreView = CollectionViewSource.GetDefaultView(collection);
this.LogEntriesStoreView.Filter = new Predicate<object>(Contains);
this.LogEntriesStoreView.Filter += new FilterEventHandler(ShowOnlyBargainsFilter);
this._view.SetDataContext(this);
this._view.ShowIView();
}
private void OKRun()
{
MessageBox.Show("One Click");
}
private void LostFocusOKRun()
{
MessageBox.Show("LostFocus");
}
private void TextChanged()
{
}
private void ShowOnlyBargainsFilter(object sender, FilterEventArgs e)
{
}
public bool Contains(object de)
{
return true;
}
full code, i added a predicate in me code. All made for example on msdn
EventHandler should work for CollectionViewSource LogEntriesStoreView.
There is a difference between implementation of Filter for CollectionView and CollectionViewSource.
https://msdn.microsoft.com/en-us/library/system.windows.data.collectionview.filter(v=vs.110).aspx
https://msdn.microsoft.com/en-us/library/system.windows.data.collectionviewsource.filter(v=vs.110).aspx

Event to refresh UserControl Display

I have a UserControl and a class for updating/storing results in a database. I need to automatically refresh the UserControlResultDislpay upon storing data. I have created and event to trigger a refresh when an Update occurs. I have the following code:
Class InstrumentTest:
public delegate void UpdateResultDisplay(object sender, EventArgs e);
public event UpdateResultDisplay RefreshDisplay;
protected virtual void OnNewResult(EventArgs e)
{
if (RefreshDisplay != null)
RefreshDisplay(this, e);
}
public void UpdateResultDB(ResultDataJFTOT resultData)
{
AnalysisListCommon myresult = PContext.GetInstance().DbHandlerLocal.StoredResult(
resultData.SampleId,
resultData.TestDate.ToString("yyyy-MM-ddTHH:mm", CultureInfo.InvariantCulture),
resultData.InstrumentSn,
StringRepository.constStringSampleName);
if (myresult != null)
{
Result r = new Result(new Guid(myresult.ResultId));
ResultData rd = r.GetResultData("Rating", FindResultDataMode.byVariableIdentifier);
string xmlTubeRating = resultData.tRating.ToString().Replace("#LT#", "<");
rd.Text = xmlRating;
rd.Store();
rd = r.GetResultData("TestDate", FindResultDataMode.byVariableIdentifier);
rd.Text = resultData.Date.ToString();
rd.Store();
OnNewResult(EventArgs.Empty);
}
else
{
AddTestToQueue(resultData);
}
}
public static InstrumentTest Instance()
{
//If instance is null create a new instance of the InstrumentTest
if (instrumentTestInstance == null)
{
instrumentTestInstance = new InstrumentTest();
}
return instrumentTestInstance;
}
Code from UserControl:
public UserControlResultDisplay()
{
this.InitializeComponent();
this.InitializeUIStrings();
this.InitializePlot();
EventListener(resultChanged);
}
private InstrumentTest resultChanged = InstrumentTest.Instance();
public void EventListener(InstrumentTest resultChanged)
{
//resultChanged = (InstrumentTest)obj;
resultChanged.RefreshDisplay += DisplayNewResultData;
}
private void DisplayNewResultData(object sender, EventArgs e)
{
RefreshCurrentResult();
}

Combobox SelectedItem property return always and show always the first item

I have 3 combobox ObjetivosCB, FrecuenciasCB and ResponsablesCB in my form as shows below
public partial class Form_Indicador : Form
{
public Indicador Indicador { get; set; }
private void Form_AgregarIndicador_Load(object sender, EventArgs e)
{
if (Indicador == null)
Indicador = new Indicador();
ConfigurarObjetivosCB();
ConfigurarFrecuenciasCB();
ConfigurarResponsablesCB();
CargarPropiedadesIndicador();
}
private void ConfigurarResponsablesCB()
{
ResponsableCB.DataSource = ResponsableRepository.Instance.All();
ResponsableCB.DisplayMember = "Area";
if (Indicador.Responsable == null)
ResponsableCB.SelectedIndex = -1;
}
private void ConfigurarFrecuenciasCB()
{
FrecuenciasCB.DisplayMember = "Periodo";
FrecuenciasCB.DataSource = IndicadorRepository.Instance.AllFrecuencias();
if (Indicador.Frecuencia == null)
FrecuenciasCB.SelectedIndex = -1;
}
private void ConfigurarObjetivosCB()
{
ObjetivosCB.DataSource = _objetivoFachada.All();
ObjetivosCB.DisplayMember = "Nombre";
if (Indicador.Objetivo == null) ObjetivosCB.SelectedIndex = -1;
}
private void CargarPropiedadesIndicador()
{
ObjetivosCB.DataBindings.Add("SelectedItem", Indicador, "Objetivo");
ResponsableCB.DataBindings.Add("SelectedItem", Indicador, "Responsable");
FrecuenciasCB.DataBindings.Add("SelectedItem", Indicador, "Frecuencia");
}
}
The problem is that FrecuenciasCB.SelectedItem and ResponsablesCB.SelectedItem always show and return the first item but ObjetivosCB.SelectedItem works fine. I am not understand... three methods has the same logic. What am I doing wrong?
I have been solved! The problem was a wrong definition for Equals() in Indicador and Frecuencia.

Categories