Is the verbose version better or verboten? - c#

I've been populating a combobox this way (getRoundingMethodVals() returns a List<String>):
comboBoxRounding.DataSource = RateSetupData.getRoundingMethodVals();
...but I saw on a StackOverflow answer the following:
comboBox1.DataSource = new BindingSource(dict, null);
...which makes me wonder if I should change my code to:
comboBoxRounding.DataSource = new BindingSource(RateSetupData.getRoundingMethodVals(), null);
Is this a six-of-one-and-half-a-dozen-of-the-other situation? Or does one way hold a strong advantage over the other?

Depends on what you want to do. If you just need to populate the comboBox for a user to select a value, then your first way works very well. It's a one way data flow: from lsit to control. In your case, a simple List(Of String) doesn't need a binding source.
However, if you have a much more complex object and want a change in the combobox value to also change the value of that object, you would use the BindingSource. This creates a two-way data flow. (For this scenario, you could use a BindingList which implements many of the BindingSource interfaces.)

Related

How to populate dropdown box with indices list

Was hoping this could be a quick answer. New to C# and NEST (as is probably obvious from my previous posts).
I am using NEST to query my ES instance and have built a small winform application to help accomplish the task. I would like to have one of the comboboxes on my winform populate dynamically with the names of the indices from my cluster.
So far I have used:
var node = new Uri("http://xxx.xxx.x.xxx:xxx");
var settings = new ConnectionSettings(node);
var client = new ElasticClient(settings);
var myindexes = client.CatIndices();
I cannot for the life of me figure out how to populate the values of my combobox with the values store in "myindexes"
I have tried
combobox1.value = myindexes.ToList();
but can't see to figure out how to go one level deeper.
I know it is a simple question, but I would really appreciate the help if somebody could spare a few moments.
Thanks very much for the help as always!
Mick
Supposing myindexes is an object that implement IList or an Array. You can use either of these options:
ComboBox.DataSource
this.comboBox1.DataSource = myindexes;
ComboBox.Items.AddRange
this.comboBox1.Items.AddRange(myindexes.Cast<object>().ToArray());
Note:
The text that will be shown for items in ComboBox is the result of ToString method.
If you are showing a complex object, using DataSource way, you can set DisplayMember to one of properties of your complex object to show in ComboBox.
The object that you want to set to DataSource property, should be an object that implements the IList interface or an Array. If it's not, you should first convert it to the expected mentioned types.
you may use BindingSource
BindingSource bs = new BindingSource();
bs.DataSource = myindexes.ToList();
comboBox1.DataSource = bs;

updating datagrid with BindingList

I've been looking at the difference between a BindingList and an observablecollection and List. From what I've read, it seems like the BindingList is the only collection type that will notify if an object in it has one of its properties changed. I cannot get this to work.
I have a property on a ViewModel called Matches, which returns a BindingList created out of a list of CarMatch objects in another class. (Cars m_Cars = new Cars();) My DataGrid on the View is bound to this Matches property in the VM.
public BindingList<CarMatch> Matches
{
get
{
Return new BindingList<CarMatch>(m_Cars.Matches);
}
}
Now, in the code I change one of the CarMatch object's properties, say.. automaticTrans = true from false. Matches[0].automaticTrans = true. I want to see that change in the DataGrid. Without implementing INotifyPropertyChanged inside of the CarMatch class, is there a way to update the datagrid from the viewmodel? Using INotifyPropertyChanged on Matches does not seem to do it. There is something about this I just don't understand, and could use an example to look at.
CarMatch (not Matches) has to implement INotifyPropertyChanged. But consider using ObservableCollection unless you really need some of the additional scenarios offered by BindingList: with ObservableCollection, INotifyPropertyChanged comes for free. And, more importantly, BindingList doesn't scale well.
try
dataGrid.Items.Refresh();
but keep in mind that is a expensive call if you have lots of data and you call it several times in a short period of time.

Bind an object which has a property of type List<> to a repeater

I've created two classes in business layer.
the first one is called Users with id (int), pass (string) and privileges (Privilege) properties and the second one is called Privilege and has id (int) and privilegeName (string) properties.
I've a method that returns all the users, and I use a repeater (actually I bind it to a DataList to auto create the ItemTemplate for me and then use a repeater) and it works and displays all the properties well except for my List property. it generates instead something like this System.Collections.Generic.List`1[WebApplication2.Public.BLL.Users]
I want to display it in a friendly way like "User Privileges : Privi1, Privi2" but still I want to keep the layers of my application clean and structured, for example I won't store them in a database in the same table and just store them as a text and append it.
I hope to find a simple and good solution...Thanks in advance guys =)
PS : I don't want to display the object Privilege, I want to display privilege.privilegeName
When using repeaters, there are two approaches, one is the one suggested by Bugai13: to have a custom property that displays it. This is fine for certain types of nested data.
Your other option is to just have a repeater inside a repeater, and bind it appropriately (to what would be a list assigned to your main data object, depending on how you O/R Mapper works).
You can have the code for the custom display property not in the data model, but in your presentation layer somewhere (depending on your framework/design), so it's not a "bad" thing to do that. It's up to you, with whatever "feels" best.
Just create property at your Bussiness object, and bind it:
public string PrivilegiesString
{
get
{
var sb = new StringBuilder("User Privileges : ");
foreach(var item in privileges)
{
sb.AppendFormat("{0}, ",item.privilegeName);
}
return sb.ToString();
}
}

Many-to-Many Databinding in LINQ

I've looked all over and haven't been able to find a clear answer to a seemingly common question: How can I do two-way databinding over a many-to-many relationship in ASP.net?
I have the following database structure:
I am currently writing a page for editing or adding a User record. Databinding things such as name and password is simple, but what I really need it to be able to display a list of all PhoneGroups and choose one or more from the list. How do I do this?
I tried a CheckBoxList, but while I can display the list of PhoneGroups, How do I bind the Checked state of each box based on whether the user has access? Some solutions use a loop in the OnDataBound event of the CheckBoxList. If I do this, how do I update the database when the checked state changes? I could go the brute force approach and write code to do this, but isn't there something that can make this simpler? It seems like such a common scenario.
Update #1
I am currently using Devart's LinqConnect, but I am open to change. The backend database is MySQL.
Yeah it is a common scenario and binding to that event is the solution i see used.
It is fairly simple when you consdier what the code is doing int he background. You could write your own custom server control, but thats a lot more difficult.
MVC may offer you an alternative ...
really why not redesign and only return the objects that they ahve permission for?
as for updating items in the database you need to say more about the architecture. But ultimatley to update an item you have to take the new item ... you have to do womthing like this
public void StoreTheUpdatedData(YourBusinessObject theBusinessObject)
{
var yourDataContext = new DataContext()
var oldObject = (from i in yourDataContext.YourbusinessObjects
where (blah equals blah to select your item and only your item)
select i).First();
//repeat for all properties in the object
oldObject.Property = theBusinessObject.Property;
yourDataContext.SaveChanges();
}
code liek that is what you need to do the update.
the save method varies depending on which ORM you are using ... I think linq2SSql uses commitChanges for instance. Been a while since i used that one.

Entity Framework - Bind Combobox to Normalised Table Field

I am currently trying to bind an entity to a form however I want to have DataConfidenceLevel (see below) bound to a combobox with ConfidenceDescription as the display member. What is the correct way to populate the combobox?
(I am currently using WPF but a Winforms answer is acceptable)
Thanks
Entity Designer http://img19.imageshack.us/img19/374/entity.png
You want to bind a collection to a control and have a releated entity - namely navigation property DataConfidenceLevel of type DataConfidenceLevel - as the display member?
That is usually achieved really simple by overriding ToString(),
public partial class DataConfidenceLevel
{
public override String ToString()
{
return this.ConfidenceDescription;
}
}
and than setting DisplayMember to the DataConfidenceLevel property of the entity you want to bind.
The answer was simpler than I was expecting.
comboBox.DataBindings.Add(new Binding("SelectedItem", this.dataBindingSource, "DataConfidenceLevel", true));
comboBox.DataSource = db.DataConfidenceLevel;
comboBox.DisplayMember = "ConfidenceDescription";
comboBox.ValueMember = "ConfidenceLevelID";
I wrote two blog entries about one approach to handling this situation - it applies to ASP.net, but it might help you out.
Here are the posts, the first one is more of an introduction to the problem, the second entry shows how to pin it all together.
I'm not sure whether this qualifies as "the correct way" but it's certainly an approach :) I'd be happy to hear back if this helps you out!
Edit: After reading danbruc's answer, you can certainly override ToString on the Navigation property as he has suggested (for read only), but that's only a partial answer.
This won't work unless your LINQ query contains the "Include" statement, e.g.
var listOfThings = (from t in db.Thingy
.Include("DataConfidenceLevel")
select t).ToList();
Omitting the .Include() means that nothing will get bound to the column.

Categories