how to make a function for validating TextInputLayout kotlin - android-studio

I want to make a function for validation of text inputs(material design) and use it multiple times
I have a working code but I know it is dirty
how to optimize it?
this is my onClick method
fun addItems(view: View) {
val name1 = etName.text.toString().trim()
val quantity1 = etQuantity.text.toString()
val gst1 = etGst.text.toString()
val amount1 = etAmount.text.toString()
fun showToast() {
runOnUiThread(kotlinx.coroutines.Runnable {
Toast.makeText(this, "$name1 Added", Toast.LENGTH_LONG).show()
}) // runnable is used because activity is immediately killed and toast cannot be sowed hence it is to be done on ui tread
finish()
}
if (name1.isNotBlank() && quantity1.isNotBlank() && amount1.isNotBlank()) {
if (quantity1.toInt() != 0) {
if (amount1.toInt() != 0) {
Thread {
val db = Room.databaseBuilder(this, AppDb::class.java, "BookDB")
.build()
val item = ItemEntity()
item.itemName = name1
item.quantity = quantity1
item.amount = amount1
if (boolProcessWithGST) {
if (gst1.isNotBlank()) {
if (gst1.toInt() != 0) {
// process with GST
item.gst = gst1
db.abstractItemDao().saveItems(item)
showToast()
} else runOnUiThread {
tilGST.error = "Tax can't be 0%"
etGst.requestFocus()
} // ui operation only works on main/ui thread
} else runOnUiThread {
tilGST.error = "Disable toggle if no TAX"
etGst.requestFocus()
}
} else {
// process without gst
db.abstractItemDao().saveItems(item)
showToast()
}
}.start()
} else {
tilAmount.error = "Amount can't be 0"
etAmount.requestFocus()
}
} else {
tilQuantity.error = "Quantity can't be 0"
etQuantity.requestFocus()
}
} else Toast.makeText(this, "please fill the required fields", Toast.LENGTH_LONG).show()
}
I want to use the same validation for another onClick in the same activity
I tried making a function but the android studio suggests -> Cascade if should be replaced with when. how to do so?
function I made
private fun isValidInput(): Boolean {
var isValid = true
val name1 = etName.text.toString().trim()
val quantity1 = etQuantity.text.toString()
val gst1 = etGst.text.toString()
val amount1 = etAmount.text.toString()
TransitionManager.beginDelayedTransition(root_layout)
if (name1.isEmpty()) {
tilName.isErrorEnabled = true
tilName.error = "Required"
isValid = false
} else tilName.isErrorEnabled = false
if (quantity1.isEmpty()) {
tilQuantity.isErrorEnabled = true
tilQuantity.error = "Required"
isValid = false
} else if (quantity1.toInt() == 0) {
tilQuantity.isErrorEnabled = true
tilQuantity.error = "can't be 0"
} else tilQuantity.isErrorEnabled = false
if (amount1.isEmpty()) {
tilAmount.isErrorEnabled = true
tilAmount.error = "Required"
isValid = false
}else if (amount1.toInt() == 0) {
tilAmount.isErrorEnabled = true
tilAmount.error = "can't be 0"
} else tilAmount.isErrorEnabled = false
if (gst1.isEmpty()) {
tilGST.isErrorEnabled = true
tilGST.error = "Required"
isValid = false
}else if (gst1.toInt() == 0) {
tilGST.isErrorEnabled = true
tilGST.error = "can't be 0"
} else tilGST.isErrorEnabled = false
return isValid
}

first I recommend using MVVM or any other architectural pattern(MVC, MVP, MVI ... ) to clean your code and achieve separation of concerns principle. in short, you should have a separate class for your application logic(in MVVM its called ViewModel) and repository class for accessing and saving your data like database or API call, and your activity is only responsible for the views. this will make your code much cleaner.
for starter, you can use this guide : Guide to app architecture
but there are tons of other resources out there which you can learn from
for your warning "Cascade if should be replaced with when" you can just hit Alt+enter and let the android studio do it for you. if it's not working you can do it yourself. it means something like this
with if:
if (num == 0) {
//do something
} else if (num < 5) {
//do something
} else {
//do something
}
convert to when looks like this:
when {
num == 0 -> {
//do something
}
num < 5 -> {
//do something
}
else -> {
//do something
}
}
when is called switch/case in other programming languages.

Related

How can I remove an existing topCalc?

Once a column definition has had a topCalc applied, I don't seem to be able to get rid of it. The formatter is removed, but the calculated numbers remain. I tried several ways of clearing it out, but no luck. Below is the most recent attempt. This works fine if is_group is true on the first run. However, once is_group has been false and the topCalcs applied, subsequent runs where is_group is true still have them. I have confirmed that the topCalc properties are being removed from the column definition objects.
Using Tabulator Version 4.9.3.
autoColumns:true,
autoColumnsDefinitions:function(definitions) {
let is_group = false;
if(document.getElementById("cex-item-detail").value == 1) {is_group = true;};
definitions.forEach((column) => {
if(column.field == "fpath") {
column.title = "Item";
column.visible = true;
column.headerFilter = true;
column.width = 600;
} else {
if(column.field == "cost") {
column.title = "Total Cost";
} else {
column.title = column.field.toUpperCase();
}
column.hozAlign = "right";
column.headerHozAlign = "right";
column.formatter = "money";
column.formatterParams = {precision: 0};
if(!is_group) {
column.topCalc = "sum";
column.topCalcFormatter = "money";
column.topCalcFormatterParams = {precision: 0};
} else {
delete column.topCalc;
delete column.topCalcFormatter;
delete column.topCalcFormatterParams;
}
}
});
return(definitions);
}

How to get scenario name from a scenario outline in cypress gherkin setup?

Suppose I have a test case like -
Scenario: Scenario to verify Title Matched
When Navigate to the App "Facebook"
Then verify the "TitleName" Field
How could I get the scenario name from the step definition methods corresponding to " When Navigate to the App Facebook" and "Then verify the "TitleName" Field"
Step definitions methods are -
When('Navigate to the App {string} for demo',(AppURL:string)=>{
if(AppURL=="FaceBook"){
}
});
Then('verify the Title of the page for demo',()=>
{
SampleAPPUI.verfiyTitledemo('');
});
Note: I am using cypres-cucumber with typescript
I'm doing this in a Java-Selenium-Gherkin test suite. It may not be the solution you need, but it will give you some direction about how to get the values:
#BeforeStep
public void doSomethingBeforeStep(Scenario scenario) throws Exception {
testScenario = scenario.getName().toString();
scenarioObj = scenario;
Field f = scenario.getClass().getDeclaredField("testCase");
f.setAccessible(true);
TestCase r = (TestCase) f.get(scenario);
List<PickleStepTestStep> stepDefs = r.getTestSteps()
.stream()
.filter(x -> x instanceof PickleStepTestStep)
.map(x -> (PickleStepTestStep) x)
.collect(Collectors.toList());
PickleStepTestStep currentStepDef = stepDefs.get(currentStepIndex);
testCase = currentStepDef.getStepText();
}
Also, see here and here
This works perfectly for me, though I'm not using TS, the logic behind it should give you a good starting point:
function getScenarioName(){
const _onRunnableRun = Cypress.runner.onRunnableRun
Cypress.runner.onRunnableRun = function (runnableRun, runnable, args) {
const r = runnable
const isHook = r.type === 'hook'
const isAfterAllHook = isHook && r.hookName.match(/after all/)
const isBeforeHook = isHook && r.hookName.match(/before each/)
const test = r.ctx.currentTest || r
var testTitle = test.title //this is the test title
const next = args[0]
if (
isHook &&
r.ctx.currentTest &&
r.ctx.currentTest.trueFn &&
!isAfterAllHook
) {
return next.call(this)
}
const onNext = function (err) {
const fail = function () {
return next.call(this, err)
}
const noFail = function () {
test.err = null
return next.call(this)
}
if (err) {
if (test._retries === -1) {
test._retries = getDefaultRetries()
}
if (isBeforeHook && test._currentRetry < test._retries) {
test.trueFn = test.fn
test.fn = function () {
throw err
}
return noFail()
}
}
return fail()
}
args[0] = onNext
return _onRunnableRun.apply(this, [runnableRun, runnable, args])
}
}

Show only one partial view among many in ajax success method

Here is my controler action method......from that action i want to return a partial view which is conditionaly true....and show this partial view in ajax success method....
public ActionResul InsertPestType (PestTypeViewModel model)
{
if (ModelState.IsValid == true)
{
pest_type emp = new pest_type();
ViewBag.emp = db.pest_type.SingleOrDefault(x => x.pest_type_name
== model.pest_type_name && x.isdeleted == false);
if (ViewBag.emp != null)
{
emp = ViewBag.emp;
}
if (emp.pest_type_name == model.pest_type_name)
{
ViewBag.Message = "This Pest Type is already exist in the
record";
return PartialView("Insert_PestType", model);
}
else
{
emp.pest_type_name = model.pest_type_name;
emp.isdeleted = false;
db.pest_type.Add(emp);
db.SaveChanges();
List<pest_type> model1 = db.pest_type.Where(x => x.isdeleted
== false).ToList();
ViewBag.pesttypelist = model1;
return PartialView("pest_type_partial", model);
}
}
else
return PartialView("inex_partial", model);
}
Below is my ajax success method.......here i want to show only one partial view which is true ocording to the condition...........Now my question is that how can i differentiate between two partial views in ajax success method??
var success=function(response)
{
if ()
{
$("#RegisterPestTypeModel").modal('hide')
$("#dvCategoryResults").html(response.AjaxReturn)
}
else
{
$("#PestTypeModalBody").html(response)
}

Windows Form in a Revit Addin

I have written quite a few different add-ins now but I keep struggling to get a windows form working on Revit. The program builds fine and I have the dll set up for Revit to access.
Here are the different sections of my code. The program is more extensive than what is seen but I believe that the problem is a reference issue or a problem with my ADDIN file. Maybe there is a different way I need to set up my ADDIN file since I have a windows form in it?? Let me know.
Here is a Dropbox folder with the screenshots in it.
Let me know if there is anything else you need to see. The error in Revit says it has to do with the FullName but I believe I put it in the ADDIN file correctly, and I did it the same as I had for other ADDINs.
Thank you for your help!
[TransactionAttribute(TransactionMode.Manual)]
[RegenerationAttribute(RegenerationOption.Manual)]
public class CicuitChecker : IExternalCommand
{
public Result Execute(
ExternalCommandData commandData,
ref string message,
ElementSet elements)
{
//set document variable
Document document = commandData.Application.ActiveUIDocument.Document;
using (Transaction trans = new Transaction(document))
{
trans.Start("Circuit Checker");
UIApplication uiApp = commandData.Application;
Document doc = uiApp.ActiveUIDocument.Document;
//run through looped form in case of user not selecting needed fields, and store what family the user wants the program to check
Boolean messedUp = false;
Boolean All = false, lightF = false, recep = false, elecEquip = false, equipCon = false, junc = false, panels = false;
FilteredElementCollector collector = new FilteredElementCollector(doc), collector2 = new FilteredElementCollector(doc);
while (messedUp)
{
CircuitChecker.CircuitCheckerForm form = new CircuitChecker.CircuitCheckerForm();
form.ShowDialog();
//Get application and document objects
foreach (String item in form.getSelectionElementsLB())
{
if (item.Equals("All"))
{
All = true;
break;
}
else if (item.Equals("Lighting Fixtures"))
{
lightF = true;
}
else if (item.Equals("Recepticales"))
{
recep = true;
}
else if (item.Equals("Electrical Equipment (including Panels)"))
{
elecEquip = true;
}
else if (item.Equals("Junctions"))
{
junc = true;
}
else
{
messedUp = true;
TaskDialog.Show("Error", "At least one element must be selected.");
}
}
if (form.getSelectionPlaceLB().Equals("Entire Project"))
{
collector
= new FilteredElementCollector(doc)
.WhereElementIsNotElementType();
collector2
= new FilteredElementCollector(doc)
.WhereElementIsNotElementType();
}
else if (form.getSelectionPlaceLB().Equals("Elements in Current View"))
{
collector
= new FilteredElementCollector(doc, document.ActiveView.Id)
.WhereElementIsNotElementType();
collector2
= new FilteredElementCollector(doc, document.ActiveView.Id)
.WhereElementIsNotElementType();
}
else
{
messedUp = true;
TaskDialog.Show("Error", "A place must be selected.");
}
}
Color color = new Color(138, 43, 226); // RGB
OverrideGraphicSettings ogs = new OverrideGraphicSettings();
OverrideGraphicSettings ogsOriginal = new OverrideGraphicSettings();
ogs.SetProjectionLineColor(color);
int notCircuited = 0;
//ElementId symbolId = family
ElementCategoryFilter lightFilter = new ElementCategoryFilter(BuiltInCategory.OST_LightingFixtures);
ElementCategoryFilter recepFilter = new ElementCategoryFilter(BuiltInCategory.OST_ElectricalFixtures);
ElementCategoryFilter elecEquipFilter = new ElementCategoryFilter(BuiltInCategory.OST_ElectricalEquipment);
//ElementClassFilter filter = new ElementClassFilter(typeof("Junction Boxes - Load"));
//FamilyInstanceFilter juncFilter1 = new FamilyInstanceFilter(doc, );
LogicalOrFilter first = new LogicalOrFilter(lightFilter, recepFilter);
if (All)
{
collector.WherePasses(first);
IList<Element> allArr = collector.ToElements();
foreach (Element e in allArr)
{
int cirNum = e.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_NUMBER).AsInteger();
String panel = e.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_PANEL_PARAM).AsString();
if (!(IsNumeric(cirNum)) || (panel.Equals("")) || (panel.Equals("<unnamed>")))
{
doc.ActiveView.SetElementOverrides(e.Id, ogs);
notCircuited++;
}
else
{
doc.ActiveView.SetElementOverrides(e.Id, ogsOriginal);
}
}
collector2.WherePasses(elecEquipFilter);
IList<Element> elecEquipArr = collector.ToElements();
foreach (Element e in elecEquipArr)
{
String panel = e.get_Parameter(BuiltInParameter.RBS_ELEC_PANEL_SUPPLY_FROM_PARAM).AsString();
if ((panel.Equals("")))
{
doc.ActiveView.SetElementOverrides(e.Id, ogs);
notCircuited++;
}
else
{
doc.ActiveView.SetElementOverrides(e.Id, ogsOriginal);
}
}
TaskDialog.Show("Circuit Checker", notCircuited + " lighting fixtures are not circuited in this view.");
trans.Commit();
}
if (!trans.HasEnded())
{
if (lightF)
{
collector.WherePasses(lightFilter);
IList<Element> lightArr = collector.ToElements();
foreach (Element e in lightArr)
{
int cirNum = e.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_NUMBER).AsInteger();
String panel = e.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_PANEL_PARAM).AsString();
if (!(IsNumeric(cirNum)) || (panel.Equals("")) || (panel.Equals("<unnamed>")))
{
doc.ActiveView.SetElementOverrides(e.Id, ogs);
notCircuited++;
}
else
{
doc.ActiveView.SetElementOverrides(e.Id, ogsOriginal);
}
}
}
if (recep)
{
collector.WherePasses(recepFilter);
IList<Element> recepArr = collector.ToElements();
foreach (Element e in recepArr)
{
int cirNum = e.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_NUMBER).AsInteger();
String panel = e.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_PANEL_PARAM).AsString();
if (!(IsNumeric(cirNum)) || (panel.Equals("")) || (panel.Equals("<unnamed>")))
{
doc.ActiveView.SetElementOverrides(e.Id, ogs);
notCircuited++;
}
else
{
doc.ActiveView.SetElementOverrides(e.Id, ogsOriginal);
}
}
}
if (elecEquip)
{
collector.WherePasses(elecEquipFilter);
IList<Element> elecEquipArr = collector.ToElements();
foreach (Element e in elecEquipArr)
{
String panel = e.get_Parameter(BuiltInParameter.RBS_ELEC_PANEL_SUPPLY_FROM_PARAM).AsString();
if ((panel.Equals("")))
{
doc.ActiveView.SetElementOverrides(e.Id, ogs);
notCircuited++;
}
else
{
doc.ActiveView.SetElementOverrides(e.Id, ogsOriginal);
}
}
}
if (junc)
{
collector.WherePasses(recepFilter);
IList<Element> juncArr = collector.ToElements();
foreach (Element e in juncArr)
{
int cirNum = e.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_NUMBER).AsInteger();
String panel = e.get_Parameter(BuiltInParameter.RBS_ELEC_CIRCUIT_PANEL_PARAM).AsString();
if (!(IsNumeric(cirNum)) || (panel.Equals("")) || (panel.Equals("<unnamed>")))
{
doc.ActiveView.SetElementOverrides(e.Id, ogs);
notCircuited++;
}
else
{
doc.ActiveView.SetElementOverrides(e.Id, ogsOriginal);
}
}
}
TaskDialog.Show("Circuit Checker", notCircuited + " lighting fixtures are not circuited in this view.");
trans.Commit();
}
}
return Result.Succeeded;
}
public static Boolean IsNumeric(Object Expression)
{
if (Expression == null || Expression is DateTime)
return false;
if (Expression is Int16 || Expression is Int32 || Expression is Int64 || Expression is Decimal || Expression is Single || Expression is Double || Expression is Boolean)
return true;
try
{
if (Expression is string)
Double.Parse(Expression as string);
else
Double.Parse(Expression.ToString());
return true;
}
catch { } // just dismiss errors but return false
return false;
}
}
This code is having the functionality in the 'main class.' I have since moved the functionality to the form class as konrad suggested but am still receiving the FullClassName error in Revit. Please Help!
The schedule data add-in provides a full Visual Studio solution demonstrating how to display a Windows form in a Revit add-in, including the generation of the Windows form on the fly:
http://thebuildingcoder.typepad.com/blog/2012/05/the-schedule-api-and-access-to-schedule-data.html
Here's how I usually set up my Windows Forms based External Commands. Remember that you have to create an External Command, and your addin manifest must point at this class. Then from this class you can launch the Form like so:
[Transaction(TransactionMode.Manual)]
public class SomeCommand : IExternalCommand
{
public Result Execute(
ExternalCommandData commandData,
ref string message,
ElementSet elements)
{
// Get application and document objects
UIApplication uiApp = commandData.Application;
Document doc = uiApp.ActiveUIDocument.Document;
UIDocument uidoc = uiApp.ActiveUIDocument;
try
{
SomeNamespace.SomeForm form = new SomeNamespace.SomeForm(doc);
form.ShowDialog();
return Result.Succeeded;
}
// Catch any exceptions and display them
catch (Autodesk.Revit.Exceptions.OperationCanceledException)
{
return Result.Cancelled;
}
catch (Exception ex)
{
message = ex.Message;
return Result.Failed;
}
}
}
So I have a Form class that I instantiate from my ExternalCommand and pass Document to its constructor. That way I have access to document when I am interacting with the form later. I wire up all functionality in code behind of the Form.
Agree, the OP's question is why doesn't the addin work...
From looking at the images, it seems like the issue is that Revit is not properly finding the full class name of the command.
It's a little unusual that you don't have your command class wrapped in a namespace (your form class is, for example).
I would recommend wrapping it in a namespace like "circuitchecker" - like your form class.
Then the "full name" in the addin file would become "circuitchecker.circuitchecker"
(the namespace.classname) - this helps Revit distinguish different classes that might have the same name.
side note: I don't believe that putting a URL into the Image/LargeImage fields in the addin will work - but not positive.

Why is parallel.Invoke not working in this case

I have an array of files like this..
string[] unZippedFiles;
the idea is that I want to parse these files in paralle. As they are parsed a record gets placed on a concurrentbag. As record is getting placed I want to kick of the update function.
Here is what I am doing in my Main():
foreach(var file in unZippedFiles)
{ Parallel.Invoke
(
() => ImportFiles(file),
() => UpdateTest()
);
}
this is what the code of Update loooks like.
static void UpdateTest( )
{
Console.WriteLine("Updating/Inserting merchant information.");
while (!merchCollection.IsEmpty || producingRecords )
{
merchant x;
if (merchCollection.TryTake(out x))
{
UPDATE_MERCHANT(x.m_id, x.mInfo, x.month, x.year);
}
}
}
This is what the import code looks like. It's pretty much a giant string parser.
System.IO.StreamReader SR = new System.IO.StreamReader(fileName);
long COUNTER = 0;
StringBuilder contents = new StringBuilder( );
string M_ID = "";
string BOF_DELIMITER = "%%MS_SKEY_0000_000_PDF:";
string EOF_DELIMITER = "%%EOF";
try
{
record_count = 0;
producingRecords = true;
for (COUNTER = 0; COUNTER <= SR.BaseStream.Length - 1; COUNTER++)
{
if (SR.EndOfStream)
{
break;
}
contents.AppendLine(Strings.Trim(SR.ReadLine()));
contents.AppendLine(System.Environment.NewLine);
//contents += Strings.Trim(SR.ReadLine());
//contents += Strings.Chr(10);
if (contents.ToString().IndexOf((EOF_DELIMITER)) > -1)
{
if (contents.ToString().StartsWith(BOF_DELIMITER) & contents.ToString().IndexOf(EOF_DELIMITER) > -1)
{
string data = contents.ToString();
M_ID = data.Substring(data.IndexOf("_M") + 2, data.Substring(data.IndexOf("_M") + 2).IndexOf("_"));
Console.WriteLine("Merchant: " + M_ID);
merchant newmerch;
newmerch.m_id = M_ID;
newmerch.mInfo = data.Substring(0, (data.IndexOf(EOF_DELIMITER) + 5));
newmerch.month = DateTime.Now.AddMonths(-1).Month;
newmerch.year = DateTime.Now.AddMonths(-1).Year;
//Update(newmerch);
merchCollection.Add(newmerch);
}
contents.Clear();
//GC.Collect();
}
}
SR.Close();
// UpdateTest();
}
catch (Exception ex)
{
producingRecords = false;
}
finally
{
producingRecords = false;
}
}
the problem i am having is that the Update runs once and then the importfile function just takes over and does not yield to the update function. Any ideas on what am I doing wrong would be of great help.
Here's my stab at fixing your thread synchronisation. Note that I haven't changed any of the code from the functional standpoint (with the exception of taking out the catch - it's generally a bad idea; exceptions need to be propagated).
Forgive if something doesn't compile - I'm writing this based on incomplete snippets.
Main
foreach(var file in unZippedFiles)
{
using (var merchCollection = new BlockingCollection<merchant>())
{
Parallel.Invoke
(
() => ImportFiles(file, merchCollection),
() => UpdateTest(merchCollection)
);
}
}
Update
private void UpdateTest(BlockingCollection<merchant> merchCollection)
{
Console.WriteLine("Updating/Inserting merchant information.");
foreach (merchant x in merchCollection.GetConsumingEnumerable())
{
UPDATE_MERCHANT(x.m_id, x.mInfo, x.month, x.year);
}
}
Import
Don't forget to pass in merchCollection as a parameter - it should not be static.
System.IO.StreamReader SR = new System.IO.StreamReader(fileName);
long COUNTER = 0;
StringBuilder contents = new StringBuilder( );
string M_ID = "";
string BOF_DELIMITER = "%%MS_SKEY_0000_000_PDF:";
string EOF_DELIMITER = "%%EOF";
try
{
record_count = 0;
for (COUNTER = 0; COUNTER <= SR.BaseStream.Length - 1; COUNTER++)
{
if (SR.EndOfStream)
{
break;
}
contents.AppendLine(Strings.Trim(SR.ReadLine()));
contents.AppendLine(System.Environment.NewLine);
//contents += Strings.Trim(SR.ReadLine());
//contents += Strings.Chr(10);
if (contents.ToString().IndexOf((EOF_DELIMITER)) > -1)
{
if (contents.ToString().StartsWith(BOF_DELIMITER) & contents.ToString().IndexOf(EOF_DELIMITER) > -1)
{
string data = contents.ToString();
M_ID = data.Substring(data.IndexOf("_M") + 2, data.Substring(data.IndexOf("_M") + 2).IndexOf("_"));
Console.WriteLine("Merchant: " + M_ID);
merchant newmerch;
newmerch.m_id = M_ID;
newmerch.mInfo = data.Substring(0, (data.IndexOf(EOF_DELIMITER) + 5));
newmerch.month = DateTime.Now.AddMonths(-1).Month;
newmerch.year = DateTime.Now.AddMonths(-1).Year;
//Update(newmerch);
merchCollection.Add(newmerch);
}
contents.Clear();
//GC.Collect();
}
}
SR.Close();
// UpdateTest();
}
finally
{
merchCollection.CompleteAdding();
}
}

Resources