Setting TextBlock Visibility on selection Change - c#

Currently I have a combo box, and want to change the visibility of a TextBlock on certain selections.
Error it's producing Object reference not set to an instance of an object.
private void Selection(object sender, SelectionChangedEventArgs e)
{
if (Findpf() == 12)
{
DateAutoCompleteBox.Visibility = System.Windows.Visibility.Collapsed;
}
else
{
DateAutoCompleteBox.Visibility = System.Windows.Visibility.Visible;
}
}
Tried = Visibility.Collapsed also and same result. How do i fix this ?
public uint Findpf()
{
if (Pf.Text == "Annual")
{
return 1;
}
if (Pf.Text == "Semi-annual")
{
return 2;
}
if (Pf.Text == "Tri-Annual")
{
return 3;
}
if (Pf.Text == "Quarterly")
{
return 4;
}
if (Pf.Text == "Bi-Monthly")
{
return 6;
}
if (Pf.Text == "Monthly")
{
return 12;
}
}
Initialization of Autocompletebox Xaml
<telerik:RadAutoCompleteBox x:Name="DateAutoCompleteBox" Visibility="Visible" Width="220"></telerik:RadAutoCompleteBox>

you can try this to check what value is null
private void Selection(object sender, SelectionChangedEventArgs e)
{
if(DateAutoCompleteBox == null)
{
MessageBox.Show("DateAutoCompleteBox is null"); return;
}
if(Pf == null)
{
MessageBox.Show("Pf is null"); return;
}
if(Pf.Text == null)
{
MessageBox.Show("Pf.Text is null"); return;
}
if (Findpf() == 12)
{
DateAutoCompleteBox.Visibility = System.Windows.Visibility.Collapsed;
}
else
{
DateAutoCompleteBox.Visibility = System.Windows.Visibility.Visible;
}
}

DateAutoCompleteBox is set to null and you cant access or set properties on objects that isnt initialized.

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

Why does TextBox.GetFirstCharIndexFromLine always return 0?

I made a subclass for TextBox and tested the following method in a separate test project.
internal static int NumberOfPhysicalLinesInTextBox(TextBox tb)
{
int lc = 0;
while (tb.GetFirstCharIndexFromLine(lc) != -1)
{
++lc;
}
return lc;
}
The code Works well, but in my subclass it does not. The above static method is called only from the method UpdateVisibleScrollBars, which is called only in the following places:
from the subclass' c-tor
OnTextChanged
OnFontChanged
OnResize
The only speciality of this subclass is that it has a placeholder when the user did not enter anything in the TextBox, and this UpdateVisibleScrollBars. In this subclass NumberOfPhysicalLinesInTextBox does not return, it loops indefinitely because the GetFirstCharIndexFromLine always returns 0 when the text is the placeholder: "Enter text here...".
Update: I do not use Lines because I need the physical lines (the lines that result after Word-wrapping), so I can know if I need to show or hide the vertical scrollbar. The TextBox is set with WordWrap = true. Here is the GetFirstCharIndexFromLine method's official documentation.
Update 2: All the class' code is below (without non-English comments):
class EnhancedTextBox : TextBox
{
internal string PlaceholderText = "Enter text here...";
internal string ActualText
{
get
{
return PlaceholderShown ? "" : Text;
}
set
{
if (value == "" || value == null)
{
if (Text == PlaceholderText)
{
PlaceholderShown = true;
ActualTextChanged?.Invoke(this, EventArgs.Empty);
}
else
{
if (!Focused)
{
BeforeActualTextChanged?.Invoke(this, EventArgs.Empty);
ProgrammaticTextChange = true;
Text = PlaceholderText;
ProgrammaticTextChange = false;
PlaceholderShown = true;
ActualTextChanged?.Invoke(this, EventArgs.Empty);
}
else
{
PlaceholderShown = false;
ActualTextChanged?.Invoke(this, EventArgs.Empty);
}
}
}
else
{
if (Text != value)
{
BeforeActualTextChanged?.Invoke(this, EventArgs.Empty);
ProgrammaticTextChange = true;
Text = value;
ProgrammaticTextChange = false;
}
PlaceholderShown = false;
ActualTextChanged?.Invoke(this, EventArgs.Empty);
}
}
}
internal Color _PlaceholderForeColor = Utils.GrayByPercent(50);
internal Color PlaceholderForeColor
{
get
{
return _PlaceholderForeColor;
}
set
{
if (_PlaceholderForeColor != value)
{
_PlaceholderForeColor = value;
Invalidate();
}
}
}
internal Color _NormalForeColor = Color.Empty;
internal Color NormalForeColor
{
get
{
return _NormalForeColor;
}
set
{
if (_NormalForeColor != value)
{
_NormalForeColor = value;
Invalidate();
}
}
}
internal bool _PlaceholderShown = true;
internal bool PlaceholderShown
{
get
{
return _PlaceholderShown;
}
set
{
if (_PlaceholderShown != value)
{
_PlaceholderShown = value;
ForceUpdatePlaceholderShown(value);
}
}
}
internal void ForceUpdatePlaceholderShown(bool value)
{
ForeColor = value ? PlaceholderForeColor :
NormalForeColor;
Invalidate();
}
public EnhancedTextBox() : base()
{
NormalForeColor = ForeColor;
ProgrammaticTextChange = true;
Text = PlaceholderText;
ProgrammaticTextChange = false;
PlaceholderShown = true;
ForceUpdatePlaceholderShown(true);
UpdateVisibleScrollBars();
}
protected override void OnEnter(EventArgs e)
{
HidePlaceholder();
base.OnEnter(e);
}
private void HidePlaceholder()
{
if (PlaceholderShown)
{
ProgrammaticTextChange = true;
Text = "";
ProgrammaticTextChange = false;
PlaceholderShown = false;
}
}
protected override void OnLeave(EventArgs e)
{
ShowPlaceholder();
base.OnLeave(e);
}
private void ShowPlaceholder()
{
if (Text == "")
{
ProgrammaticTextChange = true;
Text = PlaceholderText;
ProgrammaticTextChange = false;
PlaceholderShown = true;
}
}
internal static int NumberOfPhysicalLinesInTextBox(TextBox tb)
{
int lc = 0;
while (tb.GetFirstCharIndexFromLine(lc) != -1)
{
++lc;
}
return lc;
}
internal bool ProgrammaticTextChange = false;
/// <summary>
/// Do not use this event using handlers. Use ActualTextChanged instead.
/// </summary>
/// <param name="e"></param>
protected override void OnTextChanged(EventArgs e)
{
if (ProgrammaticTextChange)
{
return;
}
ActualText = Text;
base.OnTextChanged(e);
UpdateVisibleScrollBars();
}
private bool busy = false;
private void UpdateVisibleScrollBars()
{
if (busy) return;
busy = true;
bool c1 = false; // chars == Text.Length; // TODO: this not working for WordWrap = false
bool c2 = NumberOfPhysicalLinesInTextBox(this) > 2;
if (c1 && c2)
{
ScrollBars = ScrollBars.Both;
}
else if (c1)
{
ScrollBars = ScrollBars.Horizontal;
}
else if (c2)
{
ScrollBars = ScrollBars.Vertical;
}
else
{
ScrollBars = ScrollBars.None;
}
ScrollToCaret();
busy = false;
}
protected override void OnFontChanged(EventArgs e)
{
base.OnFontChanged(e);
UpdateVisibleScrollBars();
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
UpdateVisibleScrollBars();
}
public event EventHandler ActualTextChanged, BeforeActualTextChanged;
}
If I replace bool c2 = NumberOfPhysicalLinesInTextBox(this) > 2; with bool c2 = false; there is no non-ending while loop, although I see that the OnResize handler is called often in debugging with a breakpoint put on the c2 line, and repeatedly clicking Continue. Then If I press Continue really fast a few times, the program starts and is usable.
Update 3: Commenting out the UpdateVisibleScrollBars call inside the OnResize handler makes everything work. How can I make the scrollbars' visibility be changed when the TextBox is just resized?
Current code:
class EnhancedTextBox : TextBox
{
internal string _PlaceholderText = "Enter text here...";
internal string PlaceholderText
{
get
{
return _PlaceholderText;
}
set
{
_PlaceholderText = value;
Invalidate();
}
}
internal Color _PlaceholderForeColor = SystemColors.GrayText;
public Color PlaceholderForeColor
{
get
{
return _PlaceholderForeColor;
}
set
{
_PlaceholderForeColor = value;
Invalidate();
}
}
[Obsolete]
internal string ActualText
{
get
{
return Text;
}
set
{
if (Text != value)
{
Text = value;
}
}
}
internal Color _NormalForeColor = Color.Empty;
internal Color NormalForeColor
{
get
{
return _NormalForeColor;
}
set
{
if (_NormalForeColor != value)
{
_NormalForeColor = value;
ForeColor = value;
}
}
}
public EnhancedTextBox() : base()
{
NormalForeColor = ForeColor;
WordWrap = true;
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == 0xf)
{
if (!this.Focused && string.IsNullOrEmpty(this.Text)
&& !string.IsNullOrEmpty(this.PlaceholderText))
{
using (var g = this.CreateGraphics())
{
TextRenderer.DrawText(g, this.PlaceholderText, this.Font,
this.ClientRectangle, this.PlaceholderForeColor, this.BackColor,
TextFormatFlags.Top | TextFormatFlags.Left);
}
}
}
}
internal static int NumberOfPhysicalLinesInTextBox(TextBox tb)
{
int lc = 0;
while (tb.GetFirstCharIndexFromLine(lc) != -1)
{
++lc;
}
return lc;
}
internal bool ProgrammaticTextChange = false;
protected override void OnTextChanged(EventArgs e)
{
base.OnTextChanged(e);
ActualTextChanged?.Invoke(this, e);
UpdateVisibleScrollBars();
}
private bool busy = false;
private Size textSize = Size.Empty;
private void UpdateVisibleScrollBars()
{
if (busy) return;
busy = true;
bool c1 = false; // chars == Text.Length; // TODO: this not working for WordWrap = false
bool c2 = NumberOfPhysicalLinesInTextBox(this) > 2;
if (c1 && c2)
{
ScrollBars = ScrollBars.Both;
}
else if (c1)
{
ScrollBars = ScrollBars.Horizontal;
}
else if (c2)
{
ScrollBars = ScrollBars.Vertical;
}
else
{
ScrollBars = ScrollBars.None;
}
ScrollToCaret();
busy = false;
}
protected override void OnFontChanged(EventArgs e)
{
base.OnFontChanged(e);
UpdateVisibleScrollBars();
}
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
//UpdateVisibleScrollBars();
}
[Obsolete]
public event EventHandler ActualTextChanged;
}

Xamarin forms android - Set floating label color when binding IsEnabled

I extend an entry and i would like that it looked like this :Entry enable and disable
Here is the renderer for android :
protected override void OnElementChanged(ElementChangedEventArgs<TextBox> e)
{
base.OnElementChanged(e);
if (e.OldElement != null) this.SetNativeControl(null);
if (e.NewElement == null) return;
if (this.Control == null)
{
var layout = this.CreateNativeControl();
this.editText.AddTextChangedListener(this);
this.editText.ImeOptions = ImeAction.Done;
if (this.Element.MaxLength != 0)
this.editText.SetFilters(new IInputFilter[] { new InputFilterLengthFilter(this.Element.MaxLength) });
this.SetNativeControl(layout);
}
this.ApplyEnabled();
this.ApplyErrorText();
this.ApplyPlaceholder();
this.ApplyText();
this.ApplyKeyboard();
this.ApplyIsWrapping();
this.ApplyBoxTextColor();
this.SetHintLabelActiveColor();
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
base.OnElementPropertyChanged(sender, e);
if (e.PropertyName == nameof(this.Element.Placeholder))
this.ApplyPlaceholder();
else if (e.PropertyName == nameof(this.Element.IsInputValid) || e.PropertyName == nameof(this.Element.IsEnabled) || e.PropertyName == nameof(this.Element.IsMandatory))
this.ApplyEnabled();
else if (e.PropertyName == nameof(this.Element.ErrorText))
this.ApplyErrorText();
else if (e.PropertyName == nameof(this.Element.Placeholder))
this.ApplyPlaceholder();
else if (e.PropertyName == nameof(this.Element.Text))
this.ApplyText();
else if (e.PropertyName == nameof(this.Element.IsWrapping))
this.ApplyIsWrapping();
else if (e.PropertyName == nameof(this.Element.Keyboard))
this.ApplyKeyboard();
else if (e.PropertyName == nameof(this.Element.TextColor))
this.ApplyBoxTextColor();
}
private void SetHintLabelDefaultColor(Color color)
{
var hint = this.textInputLayout.Class.GetDeclaredField("mDefaultTextColor");
hint.Accessible = true;
hint.Set(this.textInputLayout, new ColorStateList(new int[][] { new[] { 0 } }, new int[] { color }));
}
private void SetHintLabelActiveColor()
{
var hintText = this.textInputLayout.Class.GetDeclaredField("mFocusedTextColor");
hintText.Accessible = true;
hintText.Set(this.textInputLayout, new ColorStateList(new int[][] { new[] { 0 } }, new int[] { this.Element.FloatingLabelColor.ToAndroid() }));
}
private void ApplyText()
{
if (this.textInputLayout.EditText == null || this.textInputLayout.EditText.Text == this.Element.Text)
return;
this.textInputLayout.EditText.Text = this.Element.Text;
}
private void ApplyBoxTextColor()
{
this.textInputLayout.EditText?.SetTextColor(this.Element.TextColor.ToAndroid());
}
private void ApplyEnabled()
{
this.textInputLayout.EditText.Enabled = this.Element.IsEnabled;
this.textInputLayout.EditText.SetCompoundDrawablesRelativeWithIntrinsicBounds(null, null, null, null);
if (this.Element.IsEnabled)
{
this.ApplyIsInputValid();
this.SetHintLabelDefaultColor(this.Element.FloatingLabelColor.ToAndroid());
this.SetHintLabelActiveColor();
}
else
{
this.textInputLayout.EditText.SetPadding(0, 0, 0, 0);
this.textInputLayout.EditText.BackgroundTintList = ColorStateList.ValueOf(Color.Transparent);
this.SetHintLabelDefaultColor(Color.ParseColor("#9C9C9C"));
}
}
private void ApplyErrorText()
{
this.textInputLayout.ErrorEnabled = true;
this.textInputLayout.Error = this.Element.ErrorText;
}
private void ApplyIsInputValid()
{
if (!this.Element.IsInputValid.HasValue || this.Element.IsInputValid.Value)
{
this.textInputLayout.Error = null;
if (!this.Element.IsInputValid.HasValue || (!this.Element.IsMandatory && string.IsNullOrWhiteSpace(this.Element.Text)))
return;
this.SetIconFromKey("ce-check", "#04d1cd");
}
else
{
this.SetIconFromKey("ce-Cross_close", "#ff6161");
}
}
private void ApplyPlaceholder()
{
this.textInputLayout.HintEnabled = true;
this.textInputLayout.HintAnimationEnabled = true;
this.textInputLayout.Hint = this.Element.Placeholder;
}
private void ApplyIsWrapping()
{
if (this.Element.IsWrapping)
{
this.textInputLayout.EditText.InputType |= InputTypes.TextFlagCapSentences;
this.textInputLayout.EditText.SetHorizontallyScrolling(false);
this.textInputLayout.EditText.SetMaxLines(int.MaxValue);
}
else
{
this.textInputLayout.EditText.InputType &= ~InputTypes.TextFlagCapSentences;
this.textInputLayout.EditText.SetHorizontallyScrolling(true);
this.textInputLayout.EditText.SetMaxLines(1);
}
}
private void ApplyKeyboard()
{
this.textInputLayout.EditText.InputType = this.Element.Keyboard.ToInputType();
}
private void SetIconFromKey(string key, string color)
{
var icon = Iconize.FindIconForKey(key);
if (icon == null)
return;
var drawable = new IconDrawable(this.Context, icon).Color(Color.ParseColor(color)).SizeDp(17);
this.textInputLayout.EditText.SetCompoundDrawablesRelativeWithIntrinsicBounds(null, null, drawable, null);
}
But when property IsEnabled is binded, my floating label is gray and not blue (unless I have focus) whereas if IsEnabled = false Gray or IsEnabled = true Blue
, the floating label is in the correct color.
The only solution if found was to make element focus and unfocus immediatly after applying isEnabled if it was true.
For the life of me, I can't find a good solution. I don't know if it is me and I can't see it but I need help.
Thanks
I found a solution, in my ViewModel, by default , my binding IsEnabled will be true and I set it to false when required.
It works, thanks for your help.

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.

A ResetBindings on a BindingSource of a Grid also resets ComboBox

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.

Categories