The error I got when I change the datasource of BindingSource
"databinding cannot find a row that is suitable for all bindings row that is suitable for all bindings"
this.RemoveAllBindings(); // My work-around for the meantime
bdsOrder.DataSource = _ds.Tables["orders"]; // errors here on second time around(first time is blank datatable, second time is when i open existing record, then it errors), dataset comes from Remoting
bdsOrderDetail.DataSource = _ds.Tables["order_detail"];
bdsPhoto.DataSource = _ds.Tables["order_photo"];
bdnPhoto.BindingSource = bdsPhoto;
My Helper extension method work-around on perplexing "databinding cannot find a row..." error.
namespace MycComponentExtension
{
public static class Helper
{
public static void RemoveAllBindings(this Form form)
{
RemoveAllBindings((Control)form);
}
private static void RemoveAllBindings(this Control root)
{
foreach (Control c in root.Controls)
{
if (c.Controls.Count > 0) RemoveAllBindings(c);
root.DataBindings.Clear();
}
}
What's the meaning of "DataBinding cannot find a row..." error, if at all possible, can I eliminate my work-around on it?
I have seen this error when no DataGridView is involved, but my data source was being updated from another thread (naughty!) and my binding had FormattingEnabled=false. Changing both of these seemed to fix the problem.
Related
So I have DataGrid with DataContext set to a DataTable, and is loaded via FillJobsGrid() when Window_Loaded. This works OK, but I wanted to be able to select a specific item when launching via a command line, the args part works without an issue, just 2 args with a switch and a value. The value is the Id of a row in the JobsGrid, what I cant see is how to select this row. before running BackUpSelectedClicked()
For inspiration amongst many other pages I looked here but which ever way I approach this I have never got a datagrid.Items.count. I guess this is about which event to run my code from.
Before the mod I had:
private void FillJobsGrid()
{
using (MySqlClientWrapper db = new MySqlClientWrapper(MyConnString))
{
string sql = "SELECT * FROM backupjobs";
SetJobsTable(db.GetDataTable(sql));
JobsGrid.DataContext = GetJobsTable();
}
}
The code I was hoping would do the trick was:
if (RunFromCommandLine)
{
foreach (DataRowView job in JobsGrid.Items)
{
if (job != null)
{
DataRow jobRow = job.Row;
long id = Convert.ToInt32(jobRow["Id"]);
if (Convert.ToInt32(CommandLineJobId) == id)
{
JobsGrid.SelectedItem = job;
}
}
}
BackUpSelectedClicked();
}
I have tried inserting it in FillJobsGrid, and placing it in DataGrid.DataContextChanged, Initialised, Loaded etc. Any help appreciated.
In my Winforms C# application, I have fields with Int data type and they are set to accept null values in SQL Server database (allow nulls).
In the forms I have some textboxes which are bound to those int data type fields. If I don't enter anything while creating a new record, it accepts. If I enter a number in the textbox, it also accepts it, and then if I delete it, it doesn’t accept it anymore and even doesn't allow me to move to the next field.
If I set its value as null or "" through code, it simply ignores and does not even update changes which I made in other non int text fields.
I am using following method to update.
this.Validate();
this.itemsbindingSource.EndEdit();
this.tableAdapterManager.UpdateAll(this.sBSDBDataSet);
What can I do for the textbox to accept null values?
I have tried following.
IDTextBox.Text = "";
IDTextBox.Text = null;
I have tried following with the help of above solutions (specially Mr. Ivan) and this is how it worked out.
To clear the int field on the form:
IDTextBox.Text = String.Empty;
Then on Designer.cs file of the form, as suggested by Mr. Ivan, I searched for 'IDtextbox.DataBindings.Add' and replaced
this.IDTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.itemsbindingSource, "PictureID", true));
with
this.IDTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.itemsbindingSource, "PictureID", true, System.Windows.Forms.DataSourceUpdateMode.OnValidation, ""));
It took me a whole day to search and finally I posted my problem here, and it got solved in 1 hour.
This seems to be one of the WF data binding bugs. I can't say what exactly is causing it, but in order to make it work one should set Binding.NullValue property to "" (empty string, the default is null).
I couldn't find a way to do that in the designer, and also it would be quite annoying to locate all text boxes needed. So I would suggest you the following quick-and-dirty approach. Create a helper method like this:
public static class ControlExtensions
{
public static void FixTextBoxBindings(this Control control)
{
if (control is TextBox)
{
foreach (Binding binding in control.DataBindings)
if (binding.NullValue == null) binding.NullValue = "";
}
foreach (Control child in control.Controls)
child.FixTextBoxBindings();
}
}
and then simply include the following in your form Load event:
this.FixTextBoxBindings();
TextBox dont accept null value.
You can check if it null and set String.Empty;
If(dbValue == null)
{
IDTextBox.Text = String.Empty;
}
else
{
// here set value to your textbox
}
I have a TFS work item field that seems to exist for most work items, but sometimes doesn't.
I'm attempting to bind these workitems in a listview using a WorkItemCollection, and everything works except when I attempt binding that field.
The field itself is specified in the query select and gives no error. However the only way to get the field without throwing an error on some workitems is as so (in the .cs)::
foreach(WorkItem w in queryResults)
{
if (w.Fields.Contains("Symptom"))
{
w.Fields["Symptom"].Value.ToString();//show
}
}
as these workitems are in readonly mode, I can't just force write the value etc.. (unless I return a Dictionnary with the value paired with the workitem, but I don't think that would be the best solution...)
What I'm attempting to do is in the Listview ItemTemplate, something like this::
<div class="details">
<%# Server.HtmlEncode(Eval("Fields.Contains(\"Symptom\")? Fields[\"Symptom\"].Value : \"\";").ToString())%>
</div>
But I get the 'Contains' is not a valid 'Fields' property (because its a collection method) - I'm stuck with the eval
How can I properly evaluate and display my Symptom field?
If you use TFS 2015 or VSTS, you can use REST API to get Symptom field. The API look like:
GET http(s)://{instance}/DefaultCollection/_apis/wit/workitems?ids=xx&fields=Microsoft.VSTS.CMMI.Symptom&api-version=1.0
Or with .net Api:
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using Microsoft.TeamFoundation.Client;
using System;
namespace TestCaseProject
{
class Program
{
static void Main(string[] args)
{
var tfs =
TfsTeamProjectCollectionFactory.GetTeamProjectCollection(
new Uri("http://tfsserver:8080/tfs/CollectionName"));
var service = tfs.GetService<WorkItemStore>();
var wi = service.GetWorkItem(id);
foreach (Field field in wi.Fields)
{
Console.WriteLine("{0}: {1}", field.Name, field.Value);
}
}
}
}
Use OnItemDataBound
Nothing seemed to work directly on the page so I moved away from that approach and went with attempting to solve my problem in the codebehind, since I was already capable of sorting it out on that front.
I removed my sourceObject from my page and instead had the codebehind programmatically databind my listview. (this step is not necessary)
TFSListView.DataSource = SearchHandler.SearchTFS(searchstring);
TFSListView.DataBind();
Then I used OnItemDatabound event to be able to manage each item being bound, I check if that annoying symptom field exist for the dataitem being bound and fill up the appropriate control if it does (all this replaces one eval line, so I'm still a bit annoyed but it didn't seem to be possible directly in the aspx page)
protected void TFSListView_ItemDataBound(object sender, ListViewItemEventArgs e)
{
ListViewDataItem myitem = (ListViewDataItem)e.Item;
if (e.Item.ItemType == ListViewItemType.DataItem)
{
Control divDetails = e.Item.FindControl("divLsvDetails");
WorkItem myWI = myitem.DataItem as WorkItem;
if (myWI != null && divDetails != null)
{
if (myWI.Fields.Contains("Symptom"))
{
((HtmlGenericControl)divDetails).InnerHtml = myWI["Symptom"].ToString();
}
}
}
}
I am using a datasource to populate my datagridview with the data. However, im trying to find a way for the user to be able to hide columns that he does not want to see.
I am able to hide and show columns before the program runs using:
[Browsable(false)]
public string URL
{
get
{
return this._URL;
}
set
{
this._URL = value;
this.RaisePropertyChnaged("URL");
}
}
I cannot seem to figure out how to change the [Browsable(false)] at run time.
Any ideas how I could accomplish this?
Basically, I want to bind an "on/off" to a menu.
Apologies if im not using the right terminology when explaining my problem, I am self taught and started a few weeks ago - so still very newbie :)
Edit:
Cant hide the column because when i run my update function all columns appear again. Here is my function for updating:
private void UpdateResults()
{
Invoke(new MethodInvoker(
delegate
{
this.dgvResults.SuspendLayout();
this.dgvResults.DataSource = null;
this.dgvResults.DataSource = this._mySource;
this.dgvResults.ResumeLayout();
this.dgvResults.Refresh();
}
));
}
At run time, you can just specify the column as being invisible:
dgv.Columns["ColumnName"].Visible = false;
The way to do this properly at runtime is to provide a custom ITypedList implementation on the collection, or provide a TypeDescriptionProvider for the type, or (for single-object bindings, not lists), to implement ICustomTypeDescriptor. Additionally, you would need to provide your own filtered PropertyDescriptor implementation. Is it really worth it? In most cases: no. It is much easier to configure the grid properly, showing (or not) the appropriate columns by simply choosing which to add.
Indeed, as others had mention the purpose of BrowsableAttribute is different, but I understand what you want to do:
Let's suppose that we want to create a UserControl than wraps a DataGridView and gives the user the ability to select which columns to display, allowing for complete runtime binding. A simple design would be like this (I'm using a ToolStrip, but you can always use a MenuStrip if that's what you want):
private void BindingSource_ListChanged(object sender, ListChangedEventArgs e) {
this.countLabel.Text = string.Format("Count={0}", this.bindingSource.Count);
this.columnsToolStripButton.DropDownItems.Clear();
this.columnsToolStripButton.DropDownItems.AddRange(
(from c in this.dataGrid.Columns.Cast<DataGridViewColumn>()
select new Func<ToolStripMenuItem, ToolStripMenuItem>(
i => {
i.CheckedChanged += (o1, e2) => this.dataGrid.Columns[i.Text].Visible = i.Checked;
return i;
})(
new ToolStripMenuItem {
Checked = true,
CheckOnClick = true,
Text = c.HeaderText
})).ToArray());
}
In this case, bindingSource is the intermediary DataSource of the dataGrid instance, and I'm responding to changes in bindingSource.ListChanged.
Trying to work out this whole web part personalisation, and trying to implement it for a list box.
Well the end result will be two list boxes, with interchangeable values (ie, a value will only exist in one of the listboxes)
But I can't maintain the datasource for it. So maybe I'm going about it wrong?
This is what I have for a test H2 tag on the page
[Personalizable(PersonalizationScope.User)]
public string LabelText {
get { return h2Test.InnerText; }
set { h2Test.InnerText = value; }
}
And it works fine, if I have a textbox and use it to change the value of LabelText, then when I close the browser it automagically persists the change.
So I thought, ok, then maybe the same will work with a list box
[Personalizable(PersonalizationScope.User)]
public DomainList Domains {
get { return (DomainList)lstBxDomains.DataSource; }
set {
lstBxDomains.DataSource = value;
lstBxDomains.DataBind();
}
}
Where DomainList is just a class which extends List, and Domain is just a three field class, int, string, string.
But it doesn't, so is this too complicated for the webpart personalisation automagican, or have i just implement it wrongly (Which is more than likely)
This is my event handler to remove the items from the list:
protected void btnRemDomain_Click(object sender, EventArgs e) {
if (IsPostBack && lstBxDomains.SelectedIndex > -1) {
for (int i = 0; i < lstBxDomains.Items.Count; i++) {
if (lstBxDomains.Items[i].Selected) {
Domains.Remove(Domains.Find(d => d.ID.ToString() == lstBxDomains.Items[i].Value));
}
}
Domains = Domains;
}
}
The Domains=Domains; line is in there to see if explicitly setting the value made a difference (as Removing doesn't acutally reset the value of the field), but it doesn't. I've also tried creating a new local DomainList setting it to the global one, and then doing the remove/find on it, and then setting the local one to the global. But not working either.
I have managed to resolve this by using WebPart.SetPersonalizationDirty(this); in the set accessor of Domains, but would someone mind confirming if this is an appropriate way to do it?