if (!string.IsNullOrEmpty(View.Panel1.ToString()))
{
foreach (OtherFeatures of in FeaturesInfo)
{
if (of != null)
{
of.PAN1 = View.Panel1;
of.NumOtherFeatures = null;
of.OtherFeaturesDesc = null;
break;
}
}
}
if (!string.IsNullOrEmpty(View.Panel2.ToString()))
{
foreach (OtherFeatures of in FeaturesInfo)
{
if (of != null)
{
of.PAN2 = View.Panel2;
of.NumOtherFeatures = null;
of.OtherFeaturesDesc = null;
break;
}
}
}
if (!string.IsNullOrEmpty(View.Panel3.ToString()))
{
foreach (OtherFeatures of in FeaturesInfo)
{
if (of != null)
{
of.PAN3 = View.Panel3;
of.NumOtherFeatures = null;
of.OtherFeaturesDesc = null;
break;
}
}
}
if (!string.IsNullOrEmpty(View.Panel4.ToString()))
{
foreach (OtherFeatures of in FeaturesInfo)
{
if (of != null)
{
of.PAN4 = View.Panel4;
of.NumOtherFeatures = null;
of.OtherFeaturesDesc = null;
break;
}
}
}
if (!string.IsNullOrEmpty(View.Panel5.ToString()))
{
foreach (OtherFeatures of in FeaturesInfo)
{
if (of != null)
{
of.PAN5 = View.Panel5;
of.NumOtherFeatures = null;
of.OtherFeaturesDesc = null;
break;
}
}
}
.....
.....
I have a foreach loop like above and i'm repeating the same code inorder to pass each panel value.
I'm trying to reduce the repeated code like below( but not sure it is correct way )
if (!string.IsNullOrEmpty(View.Panel1.ToString()))
{
setpanelinfo(View.Panel1.ToString(),PAN1)
}
if (!string.IsNullOrEmpty(View.Panel2.ToString()))
{
setpanelinfo(View.Panel2.ToString(),PAN2)
}
....
....
....
public void setpanelinfo(string strpanelvalue, string PAN)
{
foreach (OtherFeatures of in FeaturesInfo)
{
if (of != null)
{
of.+ "PAN1" = strpanelvalue; // ERROR
of.NumOtherFeatures = null;
of.OtherFeaturesDesc = null;
break;
}
}
}
Is there a better way to write this above foreach logic with minimal code?
One approach to simplifying this is to use an Action callback for each specific case:
void HandlePanel(string panel, Action<OtherFeatures> action)
{
if (!string.IsNullOrEmpty(panel))
{
foreach (var of in FeaturesInfo)
{
if (of != null)
{
action(of);
of.NumOtherFeatures = null;
of.OtherFeaturesDesc = null;
break;
}
}
}
}
...
HandlePanel(View.Panel1.ToString(), of => of.PAN1 = View.Panel1);
HandlePanel(View.Panel2.ToString(), of => of.PAN2 = View.Panel2);
HandlePanel(View.Panel3.ToString(), of => of.PAN3 = View.Panel3);
HandlePanel(View.Panel4.ToString(), of => of.PAN4 = View.Panel4);
....
Use the Controls collection of the form object:
(typecast)Controls(of+"PAN1").SomeProperty = some value;
I just think foreach-ing the collection three times is a little wasteful. Maybe something like this might be a little more performant
foreach (var of in FeaturesInfo)
{
if (of != null)
{
TestAndSet(View.Panel1.ToString(), text => of.PAN1 = text);
TestAndSet(View.Panel2.ToString(), text => of.PAN2 = text);
TestAndSet(View.Panel3.ToString(), text => of.PAN3 = text);
of.NumOtherFeatures = null;
of.OtherFeaturesDesc = null;
break;
}
}
....
private void TestAndSet(String panel, Action<string> setAction)
{
if (!string.IsNullOrEmpty(panel))
{
setAction(panel);
}
}
In your case, you can do only one foreach and move the test inside of the loop.
foreach (OtherFeatures of in FeaturesInfo)
{
if (of != null)
{
of.NumOtherFeatures = null;
of.OtherFeaturesDesc = null;
if (!string.IsNullOrEmpty(View.Panel1.ToString()))
of.PAN1 = View.Panel1;
if (!string.IsNullOrEmpty(View.Panel2.ToString()))
of.PAN2 = View.Panel2;
if (!string.IsNullOrEmpty(View.Panel3.ToString()))
of.PAN3 = View.Panel3;
if (!string.IsNullOrEmpty(View.Panel4.ToString()))
of.PAN4 = View.Panel4;
if (!string.IsNullOrEmpty(View.Panel5.ToString()))
of.PAN5 = View.Panel5;
break;
}
}
Related
I'm trying to create a function InsertInOrder() that inserts an item in the correct place without disturbing the order.
Ex:
LinkedList before [3,5,6] after inserting 4 ---> [3,4,5,6].
I have created the function but some reason it's not working as expected.
I'm testing the code on a Windows form application by entering ISBNs,
What went wrong:
First I inserted 23, then I inserted 10, expecting to be placed before 23 but here's what happened (image below):
What went wrong
Please find the code below:
LinkListGen Class
class LinkListGen<T> where T : IComparable
{
private LinkGen<T> list;
public LinkListGen()
{
list = null;
}
public void AddItem(T item)
{
list = new LinkGen<T>(item, list); //create a new link on the front of the list
}
public void AppendItem(T item)
{
LinkGen<T> temp = list;
if (temp == null)
{
list = new LinkGen<T>(item);
}
else
{
while (temp.Next != null)
{
temp = temp.Next;
}
temp.Next = new LinkGen<T>(item);
}
}
public string DisplayList()
{
string buffer = "";
LinkGen<T> temp = list; //temp starts beginning of list
while (temp != null) //not at end of list
{
buffer = buffer + temp.Data.ToString() + ",";
temp = temp.Next; //move along a link
}
return buffer;
}
public void RemoveItem(T item)
{
LinkGen<T> temp = list;
LinkListGen<T> newList = new LinkListGen<T>();
while (temp != null)
{
if (item.CompareTo(temp.Data) != 0)
{
newList.AppendItem(temp.Data);
}
temp = temp.Next;
}
list = newList.list;
}
public void InsertInOrder (T item)
{
LinkGen<T> temp = list;
LinkListGen<T> newList = new LinkListGen<T>();
if (list == null)
{
AppendItem(item);
}
else
{
while (temp != null)
{
if(list.Data.CompareTo(item) < 0)
{
newList.AppendItem(list.Data);
temp = temp.Next;
}
else if(list.Data.CompareTo(item) > 0)
{
newList.AppendItem(item);
newList.AppendItem(list.Data);
temp = temp.Next;
}
newList.AppendItem(list.Data);
temp = temp.Next;
}
}
}
}
Windows Form App code
public partial class Form1 : Form
{
LinkListGen<Book> ISBNList = new LinkListGen<Book>();
public Form1()
{
InitializeComponent();
}
private void AddButton_Click(object sender, EventArgs e)
{
double insertedISBN = Convert.ToDouble(ISBNTextBox.Text);
Book newBook = new Book(insertedISBN);
ISBNList.InsertInOrder(newBook);
DisplayLabel.Text = ISBNList.DisplayList();
}
private void RemoveButton_Click(object sender, EventArgs e)
{
double insertedISBN = Convert.ToDouble(ISBNTextBox.Text);
Book removeBook = new Book(insertedISBN);
ISBNList.RemoveItem(removeBook);
DisplayLabel.Text = ISBNList.DisplayList();
}
}
Your problem, that you call AppendItem at InsertInOrder, which adds element to the end of the list, instead pure pointer manipulation.
At the same time, you shouldn't recreate list at InsertInOrder to avoid memory/time overhead.
Try next code, not tested:
public void InsertInOrder(T item)
{
var node = new LinkGen<T>(item);
if (list == null)
{
list = node;
return;
}
var current = list;
while (current != null)
{
if (current.Data.CompareTo(item) < 0)
{
// current is last element
if (current.Next == null)
{
current.Next = node;
break;
}
// current.Next.Data is equal or greater than new value
// so set new node.Next to current.Next and current.Next to new node
if (current.Next.Data.CompareTo(item) >= 0)
{
node.Next = current.Next;
current.Next = node;
break;
}
}
current = current.Next;
}
}
so I'm creating a tree structure with my data and I want to avoid nested nested nested repetition. There can be children within children within children and I need to know what data to make collapsible and give a folder icon. Is there a way to simplify this? Thanks in advance.
foreach (var i in mlist)
{
// if this is a matching child
if (i.key == dto.under.ToString())
{
// add this as a child
i.children.Add(m1);
}
//check children also
foreach (var i2 in i.children)
{
if (i2.key == dto.under.ToString())
{
// add this as a child
i2.children.Add(m1);
}
if (i2.children.Count != 0)
{
i2.folder = true;
}
else
{
i2.folder = false;
}
foreach (var i3 in i2.children)
{
if (i3.key == dto.under.ToString())
{
// add this as a child
i3.children.Add(m1);
}
if (i3.children.Count != 0)
{
i3.folder = true;
}
else
{
i3.folder = false;
}
}
}
if (i.children.Count != 0)
{
i.folder = true;
}
else
{
i.folder = false;
}
}
Here's a recursive example of your current loop
public void Traverse(List<Item> items, Item dto, Item m1)
{
foreach (var i in items)
{
// if this is a matching child
if (i.key == dto.under.ToString())
{
// add this as a child
i.children.Add(m1);
}
i.folder = i.children.Count != 0;
Traverse(i.children, dto, m1);
}
}
...
Traverse(mlist, dto, m1);
You need a recursive function
foreach (var i in mlist)
{
checkChildren(i);
}
and then
void checkChildren( List i ) // i is of type List?
{
if (i.key == dto.under.ToString())
{
// add this as a child
i.children.Add(m1);
// what is m1? you may have to pass
// this in as a parameter. I am not
// really sure what it is
}
if (i.children.Count != 0)
{
i.folder = true;
}
else
{
i.folder = false;
}
foreach (var i2 in i.children)
{
checkChildren(i2);
// this will call the same function again,
// but this time on the next level of your hierarchy
}
}
I'm getting an "Access to modified closure" error in Resharper. Is there a way to pass the task as a parameter to the lambda instead of relying upon a closure?
while (!Quitting && TaskQueue.Any())
{
foreach (var task in TaskQueue.ToArray())
{
if (Quitting || task.Code == TaskCode.Quit)
{
Quitting = true;
return;
}
if (!task.Runnable)
{
continue;
}
var thread = new Thread(() =>
{
try
{
task.Callback();
}
catch (Exception e)
{
if (task.Error != null)
{
task.Error(e);
}
}
});
thread.Start();
}
}
You could use the Thread.Start(object state) method:
while (!Quitting && TaskQueue.Any())
{
foreach (var task in TaskQueue.ToArray())
{
if (Quitting || task.Code == TaskCode.Quit)
{
Quitting = true;
return;
}
if (!task.Runnable)
{
continue;
}
var thread = new Thread(state =>
{
var taskState = (Task)state;
try
{
taskState.Callback();
}
catch (Exception e)
{
if (taskState.Error != null)
{
taskState.Error(e);
}
}
});
thread.Start(task);
}
}
which would have been equivalent to using a separate function:
private void Process(object state)
{
var task = (Task)state;
try
{
task.Callback();
}
catch (Exception e)
{
if (task.Error != null)
{
task.Error(e);
}
}
}
which you would have passed like that:
while (!Quitting && TaskQueue.Any())
{
foreach (var task in TaskQueue.ToArray())
{
if (Quitting || task.Code == TaskCode.Quit)
{
Quitting = true;
return;
}
if (!task.Runnable)
{
continue;
}
new Thread(this.Process).Start(task);
}
}
In my WPF 4.0 project, I have an ObservableCollection that contain some selected Visual3D from the view :
public ObservableCollection<Visual3D> SelectedElements
{
get { return _selectedElements; }
set
{
if (Equals(_selectedElements, value))
{
return;
}
_selectedElements = value;
RaisePropertyChanged(() => SelectedElements);
}
}
Visual3D elements are selected by clicking and the source-code in the VM is :
public HitTestResultBehavior HitTestDown(HitTestResult result)
{
var resultMesh = result as RayMeshGeometry3DHitTestResult;
if (resultMesh == null)
return HitTestResultBehavior.Continue;
// Obtain clicked ModelVisual3D.
var vis = resultMesh.VisualHit as ModelVisual3D;
if (vis != null)
{
Type visType = vis.GetType();
if (visType.Name == "TruncatedConeVisual3D" || visType.Name == "BoxVisual3D")
{
var geoModel = resultMesh.ModelHit as GeometryModel3D;
if (geoModel != null)
{
var selecteMat = geoModel.Material as DiffuseMaterial;
if (selecteMat != null) selecteMat.Brush.Opacity = selecteMat.Brush.Opacity <= 0.7 ? 1 : 0.7;
}
// Otherwise it's a chair. Get the Transform3DGroup.
var xformgrp = vis.Transform as Transform3DGroup;
// This should not happen, but play it safe anyway.
if (xformgrp == null)
{
return HitTestResultBehavior.Stop;
}
// Loop through the child tranforms.
foreach (Transform3D t in xformgrp.Children)
{
// Find the TranslateTransform3D.
var trans =
t as TranslateTransform3D;
if (trans != null)
{
// Define an animation for the transform.
var anima = new DoubleAnimation();
if (trans.OffsetY == 0)
{
DependencyProperty prop = TranslateTransform3D.OffsetZProperty;
if (Math.Abs(trans.OffsetZ) < 2)
{
anima.To = 20.5*Math.Sign(trans.OffsetZ);
Debug.Assert(SelectedElements != null, "SelectedElements != null");
}
else
{
anima.To = 1*Math.Sign(trans.OffsetZ);
SelectedElements.Add(vis);
}
// Start the animation and stop the hit-testing.
trans.BeginAnimation(prop, anima);
return HitTestResultBehavior.Stop;
}
}
}
}
}
return (HitTestResultBehavior) HitTestFilterBehavior.Continue;
}
and I want to delete one or all this Visual3D element
Thank you in advance
I have implemented this methode but it's not work :
private void UnloadProduct()
{
if (CanUnload)
{
foreach (Visual3D selectedElement in SelectedElements)
{
if (selectedElement.DependencyObjectType.Name == "TruncatedConeVisual3D")
{
var test = (TruncatedConeVisual3D) selectedElement;
int id = test.VisualId;
ElementsCollection.RemoveAt(id);
RaisePropertyChanged(() => ElementsCollection);
}
else
{
var test = (BoxVisual3D) selectedElement;
int id = test.VisualId;
ProductsCollection.RemoveAt(id);
}
}
}
}
I have the following codes and I would like to write it in a way that I have minimum duplication of codes.
if (Categories != null)
{
bool flag=false;
foreach (dynamic usableCat in Category.LoadForProject(project.ID))
{
foreach (dynamic catRow in Categories)
{
if (usableCat.ID == catRow.ID)
flag = true;
}
if (!flag)
{
int id = usableCat.ID;
Category resolution = Category.Load(id);
resolution.Delete(Services.UserServices.User);
}
}
}
if (Priorities != null)
{
bool flag = false;
foreach (dynamic usableCat in Priority.LoadForProject(project.ID))
{
foreach (dynamic catRow in Priorities)
{
if (usableCat.ID == catRow.ID)
flag = true;
}
if (!flag)
{
int id = usableCat.ID;
Priority resolution = Priority.Load(id);
resolution.Delete(Services.UserServices.User);
}
}
}
Please note that Category and priority do not have a common base type or interface that includes ID.
void DeleteUsable<Ttype>(IEnumerable<Ttype> usables, IEnumerable<Ttype> collection, Func<int, Ttype> load)
{
bool flag = false;
foreach (dynamic usableCat in usables)
{
foreach (dynamic catRow in collection)
{
if (usableCat.ID == catRow.ID)
flag = true;
}
if (!flag)
{
int id = usableCat.ID;
Ttype resolution = load(id);
resolution.Delete(Services.UserServices.User);
}
}
}
Edit:
call it:
if (Categories != null)
DeleteUsable(Category.LoadForProject(project.ID), Categories, Categoriy.Load);
if (Priorities != null)
DeleteUsables(Priority.LoadForProject(project.ID), Priorities, Priority.Load);
Let me suggest an alternative approach: Instead of factoring out the flag thing, use LINQ to remove the need for the flag loop:
if (Categories != null)
{
foreach (var usableCat in Category.LoadForProject(project.ID))
{
if (!Categories.Any(row => usableCat.ID == row.ID))
Category.Load(usableCat.ID).Delete(Services.UserServices.User);
}
}
if (Priorities != null)
{
foreach (var usablePri in Priority.LoadForProject(project.ID))
{
if (!Priorities.Any(row => usablePri.ID == row.ID))
Priority.Load(usablePri.ID).Delete(Services.UserServices.User);
}
}
I'd recommend a method like this (since you have access to dynamic types):
void DeleteUsables(dynamic usablesResource, dynamic usablesCatalog)
{
bool flag = false;
foreach (dynamic usableCat in usablesCatalog.LoadForProject(project.ID))
{
foreach (dynamic catRow in usablesResource)
{
if (usableCat.ID == catRow.ID)
flag = true;
}
if (!flag)
{
int id = usableCat.ID;
dynamic resolution = usablesCatalog.Load(id);
resolution.Delete(Services.UserServices.User);
}
}
}
which you would then call like this:
if (Categories != null)
{
DeleteUsables(Categories, Category)
}
if (Priorities != null)
{
DeleteUsables(Priorities, Priority)
}