I'm having trouble accessing the ID of a model I am adding to a ComboBox. At the moment I have a model, a preset, that contains an ID and Text. I create a list of presets through OleDB and then filter the list down before adding the contents to a ComboBox. Here is the code that does this;
var ps = new PresetService();
List<PresetModel> presetList = ps.HandleGetPresets();
List<PresetModel> filteredList = presetList.Where(filteredPreset => filteredPreset.PresetReferenceFoxPro == 3).ToList();
try
{
foreach (PresetModel preset in filteredList)
{
presetComboBox.Items.Add(preset.PresetText);
}
}
catch (Exception ex)
{
var hEs = new HandleExceptionService();
hEs.HandleException(ex.ToString());
return false;
}
Here you can see that I am adding the preset's text to the ComboBox. The issue comes however when someone wants to add a Company using one of the presets. In this case I am actually not interested in the text, I just want to add the preset's ID to the database against a company instead.
Using SelectedItem is not allowing me to access the ID, it returns a null exception. This is what I've triedl
var selectedPreset = presetComboBox.SelectedItem as PresetModel;
var presetIDToAdd = selectedPreset.PresetID;
I assume that this does not work because I have simply added the preset's Text value to the ComboBox and not it's ID. How can I add preset to a ComboBox, only display it's text but access it's ID when needed?
The problem here is that you are adding the PresetText to the ComboBox, not the PresetModel itself:
presetComboBox.Items.Add(preset.PresetText);
On top of that, you are then trying to cast the SelectedItem to a PresetModel, but it's actually the PresetText.
I would suggest using the following method.
Firstly, add the whole object to the ComboBox, like this:
presetComboBox.Items.Add(preset);
You can then define an ItemTemplate on your ComboBox to display the PresetText, or, to make things easier, just set the DisplayMemberPath:
<ComboBox ...
DisplayMemberPath="PresetText"/>
This will allow you to cast the SelectedItem to a PresetModel, but also still displaying the PresetText property in the ComboBox.
Related
I have a form that takes in an object in it's constructor and populates controls on the form from properties in that object. I am having an issue where I can't set a ComboBox's SelectedText property, or at least it isn't working how I expect it to.
public Form(ValueHoldingObject obj)
{
// yeah I know this is not a very clean way to populate the combobox, the issue
// isn't limited to the combobox so I don't think this is relevant
List<int> items = Repo.GetAllItems().Reverse();
foreach (int id in checkInPrizeIds.Take(100))
// Insert at beginning to put more recently used items at the top
combobox.Items.Insert(0, id);
combobox.DropDownHeight = 200;
combobox.SelectedText = obj.StringProperty;
}
When I am testing this form the text of the combobox isn't being populated. If I add a breakpoint on the line where I assign the text it DOES get assigned, so some event is firing (multiple focus change events probably) and making it work the way I want. Obviously I can't use a breakpoint as a fix in production code. Am I assigning this value incorrectly? Should I be using a different method to populate the values?
Further testing has reviled that it isn't just the combobox, all of my controls are only being populated correctly if I have the breakpoint.
In the constructor, you need to set the selected item, for example:
foreach ( var item in combobox.Items )
if ( (string)item == obj.StringProperty )
combobox.SelectedItem = item;
Or:
foreach ( var item in combobox.Items )
if ( (int)item == Convert.ToInt32(obj.StringProperty) )
combobox.SelectedItem = item;
It's confusing but despite its name, the property SelectedText is not really the selected item... because combo box items are objects and not strings: texts shown are a representation of the item objects using ToString().
Therefore setting the selected text will not guarantee to select an item and we can prefer setting the SelectedItem.
In addition to these considerations, you set the selected text property in the constructor after populating the combo box and that can cause problems because it is before the form and the control are drawn or something like that... that is to say perhaps before the ToString() methods are called on items to prepare the visual cache, so setting the selected text can't get a match with the list.
Setting the selected text selects an existing item if done in the form load or shown events.
private void Form_Load(object sender, EventArgs e)
{
combobox.SelectedText = obj.StringProperty;
}
ComboBox.SelectedText doesn't give me the SelectedText
ComboBox.SelectedText Property
I had a databound combobox in my windows form I populate it by a function deptload() IN FORM LOAD
public void DeptcomboLoad()
{
DataTable dt = depttrans.getDeptName();
Cmb_Department.DataSource = dt;
Cmb_Department.DisplayMember = "DepartmentName"; //CHAR
Cmb_Department.ValueMember = "DepartmentPK"; //INT
}
Now when an employee of a department (say accounts DepartmentName="Accounts " , DepartmentPK=23 ) login I want the ComboBox text to be selected as "acounts "
and when I go to get the selected value of the ComboBox I should get 23
I tried
Cmb_Department.selectedtext="Accounts"
Cmb_Department.Text="Accounts"
but its not giving the selected value
Can anyone give a suggestion
Instead of trying to put a value INTO the combobox, try to GET the SelectedItem like this:
string txt= Cmb_Department.SelectedItem.Text
or just:
string txt= Cmb_Department.SelectedText
To change selected value of the combobox you can use
SelectedItem property or SelectedIndex.
Index must be exact number in your data sourse, and Item must be exact object from datasource
You can get it to select the right item by issuing something like this:
Cmb_Department.SelectedValue = 23;
Where 23 comes from some other variable, maybe on another object, maybe from a local variable, whatever works in your case.
Now, to get the selected value you can use this statement:
var val = Cmb_Department.SelectedValue;
To get the selected text (which would be the text associated with the value):
var text = ((DataRow)Cmb_Department.SelectedItem)["DepartmentName"];
The reason I'm prescribing the aforementioned is because the SelectedText property is volatile, and the Text property doesn't always work based on how the DropDownStyle is set.
However, some would probably argue to get the same as the aforementioned you could issue this statement:
var text = Cmb_Department.Text;
Hi I have a dictionary object implemented:
public partial class Window1 : Window
{
...
public Dictionary<string, string> Dictionarycheck = new Dictionary<string, string>();
public Window1()
{
Dictionarycheck.Add("Execbuildstartingmail", "Execbuildstartingmail");
Dictionarycheck.Add("Execbuildlastmail", "Execbuildlastmail");
...
}
}
then I have xml file to be parsed. I have more than 1 of such target to be parsed. I am supposed to parse the string of the attribute "if" so over here i would need "Execexample" as a string.
<project>
...
<target if="Execexample">
...
</target>
...
</project>
To do this parsing i tried to implement this code (which i'm not sure if it is correct):
private void xmlparsingButton_Click(object sender, RoutedEventArgs e)
{
XDocument xmlDoc = XDocument.Load(#"C:\Build.xml");
var abc = from target in xmlDoc.Descendants("target")
select (string)target.Attribute("if");
foreach(string target in abc)
{
// check this value whether if it exist in the dictionary.
// if not create a checkbox for it.
}
}
For the "foreach" statement i am supposed to do a check with the dictionary object. If there is no such value in dictionary, i will create a checkbox in my tabitem 5 and the name as the string (for example ExecexamplecheckBox).
how should i implement such a foreach function?
EDIT 1:
I forgot to add something. I need to write a text to a text file if these new checkboxes are checked. How do i do that? And they are required to write to a textfile that was written previously.
Does this solve the problem?
foreach(string target in abc)
{
//check this value whether if it exist in the dictionary. if not create a checkbox for it.
if (!Dictionarycheck.ContainsKey(target))
{
CheckBox chk = new CheckBox();
chk.Text = target;
SomePanel.Controls.Add(chk);
}
}
I can see two separate problems here:
1 - Data problem
Parse the xml file and extract the necessary data to a seperate list or dictionary.
2 - User interface
Generate a series of checkboxes based on the output of the data problem.
First you should separate the data problem away from the UI. In the foreach loop build a list of objects. The object should have at least a string property, for display, and a boolean property for the checkbox to bind to.
Second, on your UI create a ItemsControl (such as a ListBox) and bind its ItemsSource to the above list, then set the ItemTemplate to a DataTemplate containing a CheckBox
<ListBox ItemsSource="{Binding Path=SomeList}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Path=DisplayString}" IsChecked="{Binding Path=Selected}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
After the user has finished checking/unchecking the list, you will be left with a list upon which to write your text lines to a file.
There are several concepts you should learn when dealing with WPF, probably the hardest to get your head around is the seperation of concern between the UI and the data, and how the data layer can feed the UI to create elements for you. There should be no need to create new checkboxes in code using this technique.
Also, you will be better off not binding directly to a dictionary (although it is possible) but you should use ObservableCollection as your ItemsSource, it will handle change notification to the UI for you.
With the looks of it, as #Jackie mentioned, you could use HashSet. It won't make a difference except that it is the correct used of the right data structure in this case.
var filePath = "PathAndFileNameOfSomeFile.txt";
var hashset = new HashSet<string> { { "Execbuildstartingmail" }, { "Execbuildlastmail" } };
var xmlString = "<project><target if=\"Execexample\"></target><target if=\"Execbuildlastmail\"></target></project>";
var xDocument = XDocument.Parse(xmlString);
var attributeValues = from attrs in xDocument.Descendants("target").Attributes("if")
select attrs.Value;
foreach (var value in attributeValues)
{
var controls = this.Controls.Find(value, true);
//No checkbox with matching name found
if (controls.Length == 0)
{
if (!hashset.Contains(value))
{
var checkbox = new CheckBox();
checkbox.Parent = tabControl1.TabPages["tabPage2"];
checkbox.Text = value;
}
}
//checkbox with the given name was found AND is checked
else if (controls.Length == 1 && ((CheckBox)controls[0]).Checked)
{
using (var writer = File.AppendText(filePath))
{
writer.WriteLine(value);
}
}
}
After your Edit
I'm not clear about what you're saying in your edit, so I'll rephrase it...
While inthe foreach, if the checkbox exists and is checked, then you need to write some test to a text file. If they are not check there is nothing to do. If a checkbox does not exist, then add it to the tab is that correct?
I've updated the code to show you how to do three things:
Find Checkboxes in your form.
See if a checkbox is checked or not
Write some text to a text file.
even of the code I've provided does not do "Exactly" what you want I believe the various parts should help you get to your end goal. If not then please simply your question and provide very clear statements of where specifically you need help.
I have a bound dropdown list populated with a table of names through a select, and databinding. it shoots selectedindexchanged that (through a postback) updates a certain gridview.
What happens is, since it runs from changing the index, the one that always comes selected (alexander) can only me chosen if you choose another one, then choose alexander. poor alexander.
What I want is to put a blanc option at the beginning (default) and (if possible) a option as second.
I can't add this option manually, since the binding wipes whatever was in the dropdown list and puts the content of the datasource.
Set the AppendDataBoundItems property to True. Add your blank, then data bind.
ddl.AppendDataBoundItems = true;
ddl.Items.Add("Choose an item");
ddl.DataSource = foo;
ddl.DataBind();
The AppendDataBoundItems property
allows you to add items to the
ListControl object before data
binding occurs. After data binding,
the items collection contains both the
items from the data source and the
previously added items.
protected void SetAddrList()
{
TestDataClassDataContext dc = new TestDataClassDataContext();
dc.ObjectTrackingEnabled = false;
var addList = from addr in dc.Addresses
from eaddr in dc.EmployeeAddresses
where eaddr.EmployeeID == _curEmpID && addr.AddressID == eaddr.AddressID && addr.StateProvince.CountryRegionCode == "US"
select new
{
AddValue = addr.AddressID,
AddText = addr.AddressID,
};
if (addList != null)
{
ddlAddList.DataSource = addList;
ddlAddList.DataValueField = "AddValue";
ddlAddList.DataTextField = "AddText";
ddlAddList.DataBind();
}
ddlAddList.Items.Add(new ListItem("<Add Address>", "-1"));
}
I created this code example using adventure works to do a little practice with Linq and it is very similar to the previous answer. Using linq still shouldn't matter for the answer the last dddlAddList.Items.Add is what you need. "Add Address" = first selected option and -1 = the value.
Ok, this has been a head scratcher for me. I have a ListBox I am binding to a linq query like so:
private IQueryable<Feed> _feeds;
public IQueryable<Feed> Feeds
{
get
{
if (_feeds == null)
{
var feedsQuery = from f in _db.Feed orderby f.Title select f;
_feeds = feedsQuery;
}
return _feeds;
}
}
public Options()
{
InitializeComponent();
this.DataContext = Feeds;
}
(For the record I've also tried List, instead of IQueryable)
Everything shows up great and I have a databound form that allows you to edit a record and all of those changes work just fine, the modified data shows up in the list.
The problem comes with I add an item. Nothing shows up in the list. The data goes into the database fine, but the only way to see the data is closing and restarting my app. I'm using the code below as an example:
Feed feed = new Feed()
{
ID = Guid.NewGuid(),
Url = "http://www.test.com",
Title = "Test"
};
_db.Feed.InsertOnSubmit(feed);
_db.SubmitChanges();
_db.Refresh(System.Data.Linq.RefreshMode.OverwriteCurrentValues);
(with or without the _db.Refresh nothing happens)
What's going on?
You are doing everything right, you jus need to use ObservableCollection. This will notify the ListBox about any changes in the list and refresh it automatically.
From MSDN
In many cases the data that you work
with is a collection of objects. For
example, a common scenario in data
binding is to use an ItemsControl
such as a ListBox, ListView, or
TreeView to display a collection of
records.
P.S. you don't need a db refresh
Unless notified otherwise, the ListBox only iterates once over its ItemsSource. Your query is only being run once.
The query object doesn't know when the database changes (and Refresh doesn't help; see below)--it's up to you to know (or anticipate) that and to rerun relevant queries at the appropriate times.
Stan R mentions ObservableCollection. That's fine, but simply storing the result of your query in an ObservableCollection won't solve the problem unless you do some work to update the collection yourself when the database changes. This means rerunning the query and manually adding new items and removing deleted items from the collection. (You could alternatively just rerun the query and set the entire result back in to the ListBox, but that means a whole new set of items will be created--not very performant, and maybe not what you want for other reasons.)
As an aside, your call to DataContext.Refresh is probably not doing what you think it is. From the docs:
This method is useful after an optimistic concurrency error to bring items into a state for another attempt. It updates the state of the primitive fields and properties on the objects.
Okay. I'm not positive this is 100% the correct way to use the ObservableCollection, but this seems to work:
private ObservableCollection<Feed> _feeds;
public ObservableCollection<Feed> Feeds
{
get
{
if (_feeds == null)
{
var feedsQuery = from f in _db.Feed orderby f.Title select f;
_feeds = new ObservableCollection<Feed>();
foreach (var item in feedsQuery)
{
_feeds.Add(item);
}
}
return _feeds;
}
}
And add my item:
Feed feed = new Feed()
{
ID = Guid.NewGuid(),
Url = "http://www.test.com",
Title = "Test"
};
_db.Feed.InsertOnSubmit(feed);
_db.SubmitChanges();
// manually update the list
Feeds.Add(feed);
It took me a little while to figure out I had to update the list manually (thanks Ben), but it all seems to work. Sorting would be nice, but I'll worry about that another time.