Concurrency Error WinForms Binding Source Navigator - sql-server

I have a form with customer info that needs to be processed one transaction per page. I'm using the binding navigator to manage my pagination.
It works in all but some cases. In the cases where it doesn't work, I have to open a different window to look up information and return it to the main form. Here is the code for that:
// save current work
updateDataTable();
// Open a window and get new customer info
// CurrentCustomer is returned from the opened window
using (SqlConnection cx = new SqlConnection(GetConnectionString()))
{
DataRowView dataRow = (DataRowView)procBindingSource.Current;
dataRow.BeginEdit();
dataRow["CUSTOMER"] = CurrentCustomer;
dataRow.EndEdit();
updateDataItems();
SqlCommand cmd = new SqlCommand(
#" select acct_no from cust_processing where id = #id ", cx);
cmd.Parameters.AddWithValue("#id", (int)dataRow["ID"]);
cx.Open();
var results = cmd.ExecuteScalar();
if (results != null)
{
dataRow.BeginEdit();
dataRow["ACCT_NO"] = results.ToString();
dataRow.EndEdit();
updateDataItems(); <------ CONCURRENCY ERROR
}
}
The error I am getting is a concurrency error. I think that I have more than one version of the row possibly ? I thought I was making sure that I was on the most recent version of the row by calling updateDataTable(). I am the only user so I know I am creating the problem myself.
Here is my update method which is called when I change pages or save and exit or want to write the commit the data:
void updateDataItems()
{
this.procBindingSource.EndEdit();
this.procTableAdapter.Update(xyzDataSet);
xyzDataSet.AcceptChanges();
}
I have tried executing updateDataItems from various places such as after I assign dataRow["ACCT_NO"] = results.ToString() or before and after assigning that.
I'm pretty much down to guess and check so any thoughts, help and advice will be appreciated and +1.

Okay -- so the problem was that I was trying to update the current row from the program and also using the binding navigator. They were not working together properly.
The solution was to add a text box to the form in the forms designer and set visible = false and bind it to ACCT_NO. Once I got the results from my other form, I just needed to set the .text property of the ACCT_NO textbox to the new value and the binding navigator managed all my updates for me correctly.
txtAcct_No.text = results.ToString();

Related

Xceed DataGrid: Filtering Details

I've got a Master/Detail DataGrid and I want to filter the details.
Here's my DataGridCollectionViewSource:
<xcdg:DataGridCollectionViewSource x:Key="Features"
Filter="ExampleFilter"
Source="{Binding Path=ItemUnderEdit.Features}"
AutoCreateDetailDescriptions="False"
AutoCreateItemProperties="False">
<xcdg:DataGridCollectionViewSource.DetailDescriptions>
<xcdg:PropertyDetailDescription RelationName="Settings"
AutoCreateDetailDescriptions="False"
AutoCreateItemProperties="False">
</xcdg:PropertyDetailDescription>
</xcdg:DataGridCollectionViewSource.DetailDescriptions>
</xcdg:DataGridCollectionViewSource>
As you can see I'm filtering it with ExampleFilter, but this only filters the master. I put a breakpoint and it never sees any details.
I cant add a filter to the Detail Descriptions in the same way. Is there any way to filter the details? Any help would be much appreciated!
I went up against this problem today - I had a simple filter for both the master and detail sections that gets turned on / off via code. For the master section, it was a simple matter of code like:
((DataGridCollectionView)grid.ItemsSource).FilterCriteriaMode = FilterCriteriaMode.None; // Off
((DataGridCollectionView)grid.ItemsSource).FilterCriteriaMode = FilterCriteriaMode.And; // On
((DataGridCollectionView)grid.ItemsSource).Refresh(); // Re-run filter.
For the details section, it should have been as simple as the following code (it wasn't though):
MyDetailDescription.FilterCriteriaMode = FilterCriteriaMode.None; // Off
MyDetailDescription.FilterCriteriaMode = FilterCriteriaMode.And; // On
Turns out, doing that will enable the new filter for any new detail sections that get generated, but not existing ones. New detail sections are generated when the master row is expanded. To get around this it turned out I needed a simple foreach loop such as:
foreach (DataGridContext context in grid.GetChildContexts()) {
((DataGridCollectionViewBase)(context.Items)).FilterCriteriaMode = PetsDetailDescriptions.FilterCriteriaMode;
}
Here's my complete(ish) code for all that:
public bool ShowDeleted {
set {
if ((grid.ItemsSource != null) && (grid.ItemsSource.GetType() == DataGridCollectionView));
DataGridCollectionView v = ((DataGridCollectionView)(grid.ItemsSource));
if (value) {
v.FilterCriteriaMode = FilterCriteriaMode.None;
MyDetailDescription.FilterCriteriaMode = FilterCriteriaMode.None;
}
else {
v.FilterCriteriaMode = FilterCriteriaMode.And;
MyDetailDescription.FilterCriteriaMode = FilterCriteriaMode.And;
}
foreach (DataGridContext context in grid.GetChildContexts()) {
((DataGridCollectionViewBase)(context.Items)).FilterCriteriaMode = PetsDetailDescriptions.FilterCriteriaMode;
}
v.Refresh();
}
}
}
I'm using that in-conjunction with a simple predefined filter criterion in the XAML. IE:
<g:DataGridItemProperty Name="IsDeleted"
DataType="{x:Type sys:Boolean}">
<g:DataGridItemProperty.FilterCriterion>
<g:EqualToFilterCriterion>
<sys:Boolean>False</sys:Boolean>
</g:EqualToFilterCriterion>
</g:DataGridItemProperty.FilterCriterion>
</g:DataGridItemProperty>
I recommend using the Xaml FilterCriterions, because if you absolutely need the Filter event, it's going to get a bit more messy. For that route, you need to do the following steps:
Tap into the event when a new child DataGridContext is added to the control.
Add a predicate reference to the context.Items.Filter property (in the code state, this is a property expecting predicate, not an event).
Write your filter code in the predicate function.
I'm not 100% sure how to achieve #1 above (as I didn't need to go that route). However, a good place to possible start is the DetailsExpanding and DetailsExpanded events of the DataGridControl. For the expanding, I'm not sure if the child DataGridContext exists yet (as there is an option to cancel the expanding). So you might have to wait until after the expanded event.
I hope this helps point you in the right direction.

RPS, windows Form & Revit API (Python)

I've been trying to build a form to create and delete Revit print Sets.
I've 2 main issues:
1) I'm able to create a print set but I cannot access its content unless I restart the Form. I get the errors below (depending if I'm defining the view_set variable or not)
List_object_has_no_attribute_Views
Local_variable_referenced_before_assignment
This is the code of the function to display the sheets of the selected Print Set
def DisplaySheetsInSet (self, sender, args):
self.curItem = CurrentSetsListBox.SelectedItem
PrintSetForm_Load
try:
view_set=[]
for i in PrintSetForm.ViewSets:
if i.Name == str(self.curItem):
view_set = i
else:
continue
Sheets=[sheet.Name for sheet in view_set.Views]
SheetsLb.BeginUpdate()
SheetsLb.Items.Clear()
for sheet in Sheets:
SheetsLb.Items.Add(sheet)
SheetsLb.EndUpdate()
except Exception as e:
popup (str(e)
2) I'm able to delete print sets once. If I try do delete another one I get the following error and I need to restart the form ( code for the function that deletes the print sets shown below)
The_referenced_object_is_not_valid
def DelPrintSet(self, sender, args):
self.curItem = CurrentSetsListBox.SelectedItems
t = Transaction (doc, 'Delete printset')
t.Start()
for viewset in PrintSetForm.ViewSets:
if viewset.Name in [str(item) for item in self.curItem]:
doc.Delete(viewset.Id)
doc.Regenerate()
else:
continue
self.Refresh()
UpdateSetNames(CurrentSetsListBox)
t.Commit()
I've tried to build a function to restart/refresh the Form but it doesn't work (code below):
global PrintSetForm_Load
def PrintSetForm_Load(self, sender):
Application.Exit()
Application.Restart()
#self.Refresh()
#self.ResetBindings()
#self.ActiveForm.Close()
sd = PrintSetForm()
sd.ShowDialog()
This gif shows the form in action:
Manage Print Sets
Any ideas or suggestions?
Thank you.
3) If I try to populate the SheetsLb with a DataSource, just the first set clicked is shown.
Sheets=[sheet.Name for sheet in view_set.Views]
SheetNumber=[sheet.get_Parameter(BuiltInParameter.SHEET_NUMBER).AsString() for sheet in view_set.Views]
SheetsLb.BeginUpdate()
SheetsLb.DataSource = None
SheetsLb.Items.Clear()
UpdatedList=[]
for number,name in zip(SheetNumber,Sheets):
UpdatedList.append(number+" - "+ name + " [ ] ")
SheetsLb.DataSource=UpdatedList
SheetsLb.EndUpdate()
1) See if this works:
It would be worth checking that there is something selected in self.viewSetsLb. Ive added a check to the code below
The view_set variable could be initialised as a boolean instead of a list
Using break in the for loop keeps things a little snappier
Ive used the more pythonic for view in PrintSetForm.viewSets rather than for i in PrintSetForm.viewSets - keeping it nice and clear
This code works for me:
self.curItem = self.viewSetsLb.SelectedItem
if not self.viewSetsLb.SelectedItem:
print 'No Printset selected!'
return
view_set = False
for view in PrintSetForm.viewSets:
if view.Name == str(self.curItem):
view_set = view
break
else:
continue
Sheets=[sheet.Name for sheet in view_set.Views]
self.sheetsLb.BeginUpdate()
self.sheetsLb.Items.Clear()
for sheet in Sheets:
self.sheetsLb.Items.Add(sheet)
self.sheetsLb.EndUpdate()
2) Its because the data in your PrintSetForm.ViewSets list is out of date. Every time you change something (ie delete a viewset), repopulate this list:
PrintSetForm.ViewSets = FilteredElementCollector(doc).OfClass(ViewSheetSet).ToElements()
Also, you shouldnt need to build a refresh button, perhaps have a class function that repopulates the Printset list and ListBox, and clears the Sheet ListBox that you call after every action?
Sounds like youre having fun mate!
It sounds as if you have an issue with the scoping and lifetime of variables. For instance, some variables may have a lifetime limited to the form display, and therefore cannot be accessed after the form is closed. You could change the lifetime of these variables, e.g., by making them static class variables instead of local instance variables. I suggest you read up on .net static class variable scope.

Printing text in Silverlight that measures larger than page

I have a silverlight application that allows people to enter into a notes field which can be printed, the code used to do this is:
PrintDocument pd = new PrintDocument();
Viewbox box = new Viewbox();
TextBlock txt = new TextBlock();
txt.TextWrapping = TextWrapping.Wrap;
Paragraph pg = new Paragraph();
Run run = new Run();
pg = (Paragraph)rtText.Blocks[0];
run = (Run)pg.Inlines[0];
txt.Text = run.Text;
pd.PrintPage += (s, pe) =>
{
double grdHeight = pe.PrintableArea.Height - (pe.PageMargins.Top + pe.PageMargins.Bottom);
double grdWidth = pe.PrintableArea.Width - (pe.PageMargins.Left + pe.PageMargins.Right);
txt.Width = grdWidth;
txt.Height = grdHeight;
pe.PageVisual = txt;
};
pd.Print(lblTitle.Text);
This simply prints the content of the textbox on the page however some of the notes are spanning larger than the page itself causing it to be cut off. How can I change my code to measure the text and add more pages OR is there a better way to do the above where it will automatically create multiple pages for me?
There are several solutions to your problem, all of them under "Multiple Page Printing Silverlight" on Google. I was having a similar problem and tried most of them. The only one that worked for me was this one:
http://www.codeproject.com/Tips/248553/Silverlight-converting-to-image-and-printing-an-UI
But honestly you should look at Google first and see whether there are better solutions to your specific problem.
Answering your question, there is a flag called HasMorePages that indicates you need a new page. Just type pe.HasMorePages and you will see.
Hope it helps
First you need to work out how many pages are needed
Dim pagesNeeded As Integer = Math.Ceiling(gridHeight / pageHeight) 'gets number of pages needed
Then once the first page has been sent to the printer, you need to move that data out of view and bring the new data into view ready to print. I do this by converting the whole dataset into an image/UI element, i can then adjust Y value accordingly to bring the next set of required data on screen.
transformGroup.Children.Add(New TranslateTransform() With {.Y = -(pageIndex * pageHeight)})
Then once the number of needed pages is reached, tell the printer to stop
'sets if there is more than 1 page to print
If pagesLeft <= 0 Then
e.HasMorePages = False
Exit Sub
Else
e.HasMorePages = True
End If
Or if this is too much work, you can simply just scale all the notes to fit onto screen. Again probably by converting to UI element.
Hope this helps

Dynamically populate GraphSource through PopulateGraphSource method - RadDiagram

I am facing an issue where my graph is tree layout and looks fine initially. However, if I choose to change GraphSource upon user input/ clicks using PopulateGraphSource like in the OrgChart example, I get all the nodes stacked on top of each other with no links and all in corner.
I tried resetting graphSource by creating a new one
this.graphSource = new GraphSource();
I also tried to use the Clear method for GraphSource. Neither did solve the problem, I keep having the same issue.
I am using
ObservableCollection<Node> hierarchicalDataSource;
to fill up my GraphSource object.
All I do is create a new one and then call
PopulateGraphSource();
method.
Similar issues: question in telerik support , telerik support different question
Try calling the Layout method on the diagram control. Here is a little fragment of code
TreeLayoutSettings settings = new TreeLayoutSettings()
{
TreeLayoutType = TreeLayoutType.TreeDown,
VerticalSeparation = 60,
HorizontalSeparation=30
};
if (this.diagram.Shapes.Count > 0)
{
settings.Roots.Add(this.diagram.Shapes[0]);
this.diagram.Layout(LayoutType.Tree, settings);
this.diagram.AutoFit();
//this.diagram.Zoom = 1;
}

Using HTMLDocument to manipulate HTML and show it in WebBrowser-control

I am trying to manipulate a requested document in the WPF WebBrowser-control. I already managed it to invoke JavaScript on loaded document, but I am not able to change the shown HTML-code in the control itself.
My (very simplified) code in the OnNavigating-Handler looks like this:
mshtml.HTMLDocument doc = (mshtml.HTMLDocument)View.browser.Document;
HTMLTableClass table = doc.getElementById("someTable") as HTMLTableClass;
if (table != null)
{
table.appendChild((IHTMLDOMNode)(doc.createElement("<tr>") as IHTMLElement));
}
doc.close();
The -element doesn't get appended to displayed document in the control.
Any hints are very appreciated!
I finally got it. Its only possible to change the content of the table by adding rows and cells which i wanted to avoid in first place. My approach was to directly change the content of the -tag, which didnt work.
mshtml.IHTMLTableRow row = table.IHTMLTable_insertRow(-1) as mshtml.IHTMLTableRow;
mshtml.IHTMLElement c = (mshtml.IHTMLElement)row.insertCell(0);
c.innerText = "some";
mshtml.IHTMLElement c1 = (mshtml.IHTMLElement)row.insertCell(1);
c1.innerText = "text";

Resources