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.
Related
I have asked this question before and it got flagged for not being detailed enough so I thought I would rephrase it and better detail my problem.
Summarise the problem:
First of all, I was following this tutorial 'Using SQLite in C# - Building Simple, Powerful, Portable Databases for Your Application' (https://www.youtube.com/watch?v=ayp3tHEkRc0). The creator of this tutorial had this form:
In the form you could add a first name and a listname and it shows up in the List People. This was his code-behind:
I followed the tutorial and I decided I would replicate this but instead of 'Person' it will display the user's statistics:
I want to be able to display the SQLite table content inside a listbox. But the problem is that in WPF there is no such thing as 'DataSource' or 'DisplayMember'. This is my code so far:
public partial class databasetestform : Window
{
List<UserStatistics> userstatistics = new List<UserStatistics>();
public databasetestform()
{
InitializeComponent();
}
private void LoadStatistics_List()
{
userstatistics = SQLiteDataAccess.LoadStatistics();
WriteUpStatisticsList();
}
public void WriteUpStatisticsList()
{
// Unsure what to do here
}
private void Load_button_Click(object sender, RoutedEventArgs e)
{
LoadStatistics_List();
UserStatistics s = new UserStatistics();
int result1;
int result2;
if(int.TryParse(AVGtxtbox.Text, out result1))
{
s.GamesPlayed = result1;
SQLiteDataAccess.SaveStatistics(s);
}
if (int.TryParse(AVGtxtbox.Text, out result2))
{
s.GamesPlayed_ScoreAverage = result2;
SQLiteDataAccess.SaveStatistics(s);
}
AVGtxtbox.Text = "";
PLYDtxtbox.Text = "";
}
}
Describe what you've tried
I've tried for many hours to find a work-around, I tried to use 'ItemsSource' instead of DataSource but I still had no work-around for 'DisplayMember'.
Hope I can get a solution to this.
Thanks,
Seems like you're on the right track.
ItemsSource is the correct property to use for your data source. It accepts any IEnumerable so your List<T> should work just fine.
Instead of DisplayMember, I think you're looking for DisplayMemberPath. You can set this to the name of a property declared on your UserStatistics object and the ListBoxItems will display the value of that property.
The C# would be as simple as:
MyListBox.ItemsSource = userstatistics;
DisplayMemberPath would usually be set on the ListBox tag in the XAML:
<ListBox Name="MyListBox" DisplayMemberPath="SomePropertyName"/>
The above gives you the simple answer, which does work, but there are a couple other concepts you should be aware of and maybe look into later on:
In WPF, one generally tries to avoid giving a UI element an explicit name and referencing it in code. The goal behind this is to try and separate the functional components of the program from the visual interface.
To acheive this, the visual components (declared in XAML) are usually connected to the functional code (written in C# or VB.NET) using data binding.
This isn't a completely strict rule, however, and I've broken it on a few occasions when it made scense, or when referencing a UI element by name was just far, far easier.
While DisplayMemberPath works for displaying the value of a single property, sometimes you need a more complex display of items. This can be accomplished using data templates and the ItemTemplate property. It requires knowledge and use of data binding.
I am writing a program where data is being displayed using a DataGridView and I was hoping there was a way to access the visible property of the columns without specifying the index location, or Column Name string value.
public class test {
public static string value1 { get; set; }
public static string value2 { get; set; }
}
I am using the LINQ to SQL datacontext to query information to be displayed into my DataGridView.
As it currently is, I can only seem to find a way to change the Columns visible property as so (assuming DataGridView is instantiated as dgvDATA)
dgvDATA.columns["value1"].visible = false;
Is there any way to do something similar to the following? I assume if there is it would be through databindings, but I tried that and couldn't figure it out.
dgvDATA.column.value1.visible = false;
I found this article stating that the DataGridView does not have this kind of ability built in but there was a workaround where you could add a database field representing if you want it visible or not.
HOWEVER the article was written in 2011 so I find it hard to believe that something like this was never implemented.
https://dotnetbuildingblocks.wordpress.com/2011/07/30/binding-datagrid-column-visibility-to-a-datacontext/
Please let me know if this is possible! Thank you
DataGridView doesn't support what you are asking for.
Anyway, if your only goal is to avoid using hardcoded field names, then using nameof() makes sense.
In your case it will be
dgvDATA.Columns[nameof(test.value1)].Visible = false;
That way you will have no issues refactoring your code later.
Apparently you want some kind of special DataGridViewColumn, where columns can be identified using some identification that is not available in a standard DataGridViewcolumn. For example you want to identify them by the PropertyInfo of the property that is shown in the column, or maybe the database column name of the database column whose values you show in this column.
In object oriented programming, if you want to create a special kind of DataGridViewColumn you should write a derived class:
class MySpecialDataGridViewColumn : DataGridViewColumn
{
public string DatabaseColumnName {get; set;}
}
Normally this would be enough: as long as you make sure that you only add MySpecialDataGridViewColumn objects to your DataGridView. When you fetch a column, typecast it to MySpecialDataGridViewColumn.
var theColumnThatDisplaysFirstName = myDataGridView.Columns // get all columns
.Cast<MySpecidalDataGridViewColumn>() // cast to your type
.Where(column => column.DatabaseCollumnName == "FirstName")
.SingleOrDefault(); // keep the ones with "FirstName"
Be aware that others will still be able to Add other kind of columns to your DataGridView. If you are afraid of this, make sure that you keep your members private and add functionality to Add / Fetch / Remove MySpecialDataGridViewColumns.
If your DataGridView is to be used by many, consider creating a UserControl that contains a private DataGridView, with functionalities to Add / Retrieve / Remove MySpecialDataGridViewColumn objects to the user control. This way others can't misuse your `DataGridView by adding other types of columns
Of course, if you want to allow others to add their own kind of Columns, you could always use OfType<MySpecialDataGridViewColumn> instead of a Cast. This way you ignore the other type of added columns, of which you are certain that they don't display your database columns
I've been looking into how best to do this and wisdom would be appreciated. For read only purposes, I've been happily using LINQ and binding it to a grid. For editing purposes, I've used the LinqDataSource control, enabled the Edit/Delete operations in the process, and I have a nice editable grid bound to some or all of the table's fields.
Now I have a situation where I want to edit a few fields in table A, but there are various values in linked table B that I want to display in that grid too (no editing of those). So my query looks like the below. The fields in tblDupes (cleared, notes) are what I want to edit, but I'd like to display those tblVoucher ones.
var theDupes = from d in db.tblDupes
where d.dupeGroup == Ref
select new
{
Ref = d.dupeGroup,
InvoiceNum = d.tblVoucher.invoiceRef,
Value = d.tblVoucher.invoiceAmtDecimal,
VendorNum = d.tblVoucher.vendorID,
VendorName = d.tblVoucher.vendorName,
Cleared = d.Cleared
Notes = d.Notes
};
A similar but different question LINQDataSource - Query Multiple Tables? sent me looking at scott Guthrie's blog entry http://weblogs.asp.net/scottgu/archive/2007/09/07/linq-to-sql-part-9-using-a-custom-linq-expression-with-the-lt-asp-linqdatasource-gt-control.aspx, where he handles various events to have a LinqDataSource with a custom query across tables. This still seems aimed at explicitly designed classes though, even if the class has only a subset of the fields.
So my question is: is there an easy way to allow committing of the changes made to the anonymous collection (a changes.Submit type action), or just an easy way to 'display' fields from another table while not involving them in the updating?
EDIT: Thinking more, it doesn't have to be anonymous really. I'd be happy to define a class to contain the elements in that query, since it won't change often. But, those elements would be across two tables, even though only one needs updating. Not sure if that suggests entity framework would be more suitable - I get the feeling it wouldn't - I don't want the whole 'model' always grouping the fields in this way.
Thanks!
Taking a wild guess here, but couldn't you listen to the LINQDataSource.Updating event and perform your save there? You would, of course, have some problems with the mapping since you cannot type the object in the LinqDataSourceUpdateEventArgs.OriginalObject.
What if you create a ViewModel instead of the anonymous type. Something like DupeVoucherViewModel.
Then in the Updating event, you could cast the LinqDataSourceUpdateEventArgs.OriginalObject to the DupeVoucherViewModel object and start mapping and saving your data.
Example
Given that you create a view model (a class) that you call DupeVoucherViewModel and bind to that like so:
var theDupes = from d in db.tblDupes
where d.dupeGroup == Ref
select new DupeVoucherViewModel
{
Ref = d.dupeGroup,
InvoiceNum = d.tblVoucher.invoiceRef,
Value = d.tblVoucher.invoiceAmtDecimal,
VendorNum = d.tblVoucher.vendorID,
VendorName = d.tblVoucher.vendorName,
Cleared = d.Cleared
Notes = d.Notes
};
Then the server tag should map the updating event like so:
<asp:LinqDataSource EnableUpdate="true" OnUpdating="LinqDataSource_Updating" />
And the code behind should contain the following method:
protected void LinqDataSource_Updating(object sender, LinqDataSourceUpdateEventArgs e)
{
// originalObject contains the unchanged object
var originalObject = (DupeVoucherViewModel)e.OriginalObject;
// newObject contains the changed object
var newObject = (DupeVoucherViewModel)e.NewObject;
// Perform your save using newObject
yourDataAccessComponent.SaveSomething(newObject);
}
You might need to include some more information in the DupeVoucherViewModel such as an ID of tblDupes or something, so that you can load that and change it.
You can read more about the LinqDataSource here: http://msdn.microsoft.com/en-us/library/bb514963.aspx
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.
I have a grid that binds a number of child data objects to columns with no issue, using the syntax defined at http://www.telerik.com/help/aspnet-ajax/grdbindingtosubobjects.html.
What I can't figure out, however, is how to aggregate a child object that is a list or collection. For example, if I have a Customer object and I want to get the customer's first street address, I would use DataField="Customer.Addresses[0].Street" on a standard GridBoundColumn.
How can I get the count of the addresses? I have tried all sorts of GridCalculatedColumn DataFields and Expressions, to no avail. I am looking for something along the lines of this:
That doesn't work, of course. In fact, if I try to do a Count on any dotted data field, I get an exception of
"System.Data.SyntaxErrorException: Syntax error in aggregate argument: Expecting a single column argument with possible 'Child' qualifier."
For example, just trying to use an expression of Count({0}) with DataFields set to Customer.FirstName (of which there is only one), causes that exception to be thrown at runtime. Doing the same thing with a non-dotted data field, such as SendDate, does not cause the same exception.
Seems like you already received an answer to this question from the Telerik forums but for people that might stumble upon this question looking for an answer.
Essentially the RadGrid does not support having Collections in its DataFields, and the supported bindable property types can be found here. So in terms of this aggregation you could either do a calculation across this collection before binding it to the RadGrid and have an aggregate column defined, or you could look into using footers much like in this demo.