How can I draw iterating ul-li List pattern? - c#

I want to draw the Html as in the Preview.
To see preview click here. View Source of the page to view the ul -li rendering.
For this I wrote a method shown below
private void DrawTree(HtmlGenericControl ParentULTag, int count)
{
for (int i = 0; i < count; i++)
{
HtmlGenericControl ChildLi = new HtmlGenericControl("li");
HtmlGenericControl ChildUl = new HtmlGenericControl("ul");
ChildLi.Controls.Add(ChildUl);
ParentULTag.Controls.Add(ChildLi);
ChildLi.InnerText = i.ToString();
DrawTree(ChildUl, i);
}
}
But it Draw it like this
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
I Initiated the method in the pageload as shown
HtmlGenericControl Initial = new HtmlGenericControl("ul");
DrawTree(Initial,4);
Whats the mistake in this code?

Try this:
private static HtmlGenericControl GenerateList(int count)
{
HtmlGenericControl parent = new HtmlGenericControl("ul");
for (int i = 1; i <= count; i++)
{
HtmlGenericControl ChildLi = new HtmlGenericControl("li");
ChildLi.InnerText = i.ToString();
HtmlGenericControl ChildUl = new HtmlGenericControl("ul");
ChildLi.Controls.Add(ChildUl);
for (int j = 1; j <= i; j++) {
HtmlGenericControl FinalLi = new HtmlGenericControl("li");
FinalLi.InnerText = j.ToString();
ChildUl.Controls.Add(FinalLi);
}
parent.Controls.Add(ChildLi);
}
return parent;
}
Edit:
You should represent your input as a tree structure. Here I used a Node object that has an ID and Children properties:
class Node
{
public int ID { get; set; }
public Node[] Children { get; set; }
public Node(int id, Node[] children)
{
ID = id;
Children = children;
}
public Node(int id)
{
ID = id;
Children = new Node[] { };
}
}
class Program
{
public static HtmlGenericControl GetList(Node root)
{
HtmlGenericControl ul = new HtmlGenericControl("ul");
GetListImpl(root, ul);
return ul;
}
private static void GetListImpl(Node root, HtmlGenericControl rootElement)
{
foreach (var item in root.Children)
{
HtmlGenericControl li = new HtmlGenericControl("li");
li.InnerText = item.ID.ToString();
if (item.Children.Length > 0)
li.Controls.Add(GetList(item));
rootElement.Controls.Add(li);
}
}
public static string HtmlGenericControlToString(HtmlGenericControl control)
{
string contents = null;
using (System.IO.StringWriter swriter = new System.IO.StringWriter())
{
HtmlTextWriter writer = new HtmlTextWriter(swriter);
control.RenderControl(writer);
contents = swriter.ToString();
}
return contents;
}
static void Main(string[] args)
{
Node root = new Node(0,
new Node[]{
new Node(1, new Node[]{
new Node(1),
new Node(2)
}),
new Node(2, new Node[]{
new Node(1),
new Node(2, new Node[]{
new Node(1)
})
})
});
var ul = GetList(root);
var html = HtmlGenericControlToString(ul);
Console.WriteLine(html);
}
}

Try this
HtmlGenericControl Initial = new HtmlGenericControl("ul");
DrawTree(ref Initial,4);
now method
private void DrawTree(ref HtmlGenericControl ParentULTag, int count)
{
for (int i = 0; i < count; i++)
{
HtmlGenericControl ChildLi = new HtmlGenericControl("li");
HtmlGenericControl ChildUl = new HtmlGenericControl("ul");
ChildLi.Controls.Add(ChildUl);
ParentULTag.Controls.Add(ChildLi);
ChildLi.InnerText = i.ToString();
DrawTree(ref ChildUl, i);
}
}

The problem was simple
private void DrawTree(HtmlGenericControl ParentULTag, int count)
{
for (int i = 0; i < count; i++)
{
HtmlGenericControl ChildLi = new HtmlGenericControl("li");
HtmlGenericControl ChildUl = new HtmlGenericControl("ul");
ChildLi.InnerText = i.ToString();
ChildLi.Controls.Add(ChildUl);
DrawTree(ChildUl, i);
ParentULTag.Controls.Add(ChildLi);
}
}
Please note the position of line ChildLi.InnerText = i.ToString();
but still don't know why its so

Related

Read Data from a CSV file

I am looking to store values from a CSV file with two Columns, I have the following class ReadFromCSVhandling the reading of the CSV file but I am having difficulty using this list to display the contents once a button is clicked. The code I have to read the CSV file is as follows;
namespace ELMFS
{
public class ReadFromCSV
{
static void ReadCSV(string[] args)
{
List<TextSpeak> TxtSpk = File.ReadAllLines(#"C:\textwords.csv")
.Skip(1)
.Select(t => TextSpeak.FromCsv(t))
.ToList();
}
}
public class TextSpeak
{
string Abreviated;
string Expanded;
public static TextSpeak FromCsv(string csvLine)
{
string[] TxtSpk = csvLine.Split(',');
TextSpeak textSpeak = new TextSpeak();
textSpeak.Abreviated = TxtSpk[0];
textSpeak.Expanded = TxtSpk[1];
return textSpeak;
}
}
}
I am trying to display the textSpeak.Abreviated in a message box but cannot seem to access it from the WPF window.
How do I use this list in other windows within the application?
any advice would be appreciated!
Thanks in advance!
First, ReadCSV method should return the generated List object (or you cannot use the list anywhere else).
Second, TextSpeak class should have properties so that you can access its member variables outside the class.
I.e. something like this should work:
namespace ELMFS
{
public class ReadFromCSV
{
public static List<TextSpeak> ReadCSV(string[] args)
{
List<TextSpeak> TxtSpk = File.ReadAllLines(#"C:\textwords.csv")
.Skip(1)
.Select(t => TextSpeak.FromCsv(t))
.ToList();
return TxtSpk;
}
}
public class TextSpeak
{
public string Abreviated { get; private set; }
public string Expanded { get; private set; }
public static TextSpeak FromCsv(string csvLine)
{
string[] TxtSpk = csvLine.Split(',');
TextSpeak textSpeak = new TextSpeak();
textSpeak.Abreviated = TxtSpk[0];
textSpeak.Expanded = TxtSpk[1];
return textSpeak;
}
}
}
private void Display(int count)
{
textBox1.Text = "";
for (int i = 0; i <= count ; i++)
{
textBox1.Text += ((dataGridView1.Rows[i].Cells[1].Value).ToString()) + (dataGridView1.Rows[i].Cells[2].Value.ToString()) + Environment.NewLine;
}
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
// your code here
string CSVFilePathName =Path.GetDirectoryName(Application.ExecutablePath).Replace(#"\bin\Debug", #"\NewFolder1\TEST.csv");
string[] Lines = File.ReadAllLines(CSVFilePathName);
string[] Fields;
Fields = Lines[0].Split(new char[] { ',' });
int Cols = Fields.GetLength(0);
DataTable dt = new DataTable();
//1st row must be column names; force lower case to ensure matching later on.
for (int i = 0; i < Cols; i++)
dt.Columns.Add(Fields[i].ToLower(), typeof(string));
DataRow Row;
for (int i = 1; i < Lines.GetLength(0); i++)
{
Fields = Lines[i].Split(new char[] { ',' });
Row = dt.NewRow();
for (int f = 0; f < Cols; f++)
Row[f] = Fields[f];
dt.Rows.Add(Row);
}
dataGridView1.DataSource = dt;
int count = 0;
if (dataGridView1.RowCount > 0)
{
count = dataGridView1.Rows.Count;
}
buttons = new Button[count];
for (int i = 0; i <count; i++)
{
buttons[i] = new Button();
buttons[i].Name = "buttons_Click" + i.ToString();
buttons[i].Text = "Click";
buttons[i].Click += new EventHandler(buttons_Click);
this.Controls.Add(buttons[i]);
buttons[i].Visible = false;
}
buttons[0].Visible = true;
// buttons[1].Visible = true;
}
catch (Exception ex)
{
MessageBox.Show("Error is " + ex.ToString());
throw;
}
}
private void buttons_Click(object sender, EventArgs e)
{
int count = dataGridView1.Rows.Count-1;
if(c <= count)
{
if (buttons[c].Name == "buttons_Click" + c.ToString())
{
buttons[c].Visible = false;
int j = c;
Display(j);
if (c != count)
{
c = c + 1;
buttons[c].Visible = true;
}
}
}
if (c == count)
{
buttons[0].Visible = true;
}
}
}
}

Cannot make EmguCV-OpenCV BOW Categorization work properly

I am trying to learn BOW object categorization. I have tried to implement the example given in the book "Practical OpenCV, Samarth Brahmbhatt" Chapter 8 (page 148)
When I save the SVM's to file on the training stage and read them on the categorization stage, the result is comletely different. (If the line
svm = notFromFile[category]; is removed, the results are wrong; if not, it is successful with the dataset provided by the book.)
When I try this code with some larger datasets, I sometimes get this exception: System.AccessViolationException' in Emgu.CV.World.dll for the line bowDescriptorExtractor.Compute(frame_g, kp, img); and the application closes. It cannot be handled.
I have tried many things but could not figure them out. Any suggestions why these are happening, and how to solve, is very appreciated.
I am using emgucv-windesktop 3.1.0.2504
My implementation:
internal class Categorizer3 : ICategorizer
{
public string Name
{
get
{
return "Categorizer3";
}
}
public bool Train()
{
try
{
initDir();
Feature2D descriptorExtractor;
Feature2D featureDetector;
List<Mat> templates;
BOWKMeansTrainer bowtrainer;
BOWImgDescriptorExtractor bowDescriptorExtractor;
init(out descriptorExtractor, out featureDetector, out templates, out bowtrainer, out bowDescriptorExtractor);
List<Tuple<string, Mat>> train_set;
List<string> category_names;
make_train_set(out train_set, out category_names);
Mat vocab;
build_vocab(descriptorExtractor, featureDetector, templates, bowtrainer, out vocab);
bowDescriptorExtractor.SetVocabulary(vocab);
Dictionary<string, Mat> positive_data;
Dictionary<string, Mat> negative_data;
make_pos_neg(train_set, bowDescriptorExtractor, featureDetector, category_names, out positive_data, out negative_data);
this.train_classifiers(category_names, positive_data, negative_data);
return true;
}
catch (Exception)
{
return false;
}
}
public event TrainedEventHandler Trained;
protected void OnTrained(string fn)
{
if (this.Trained != null)
this.Trained(fn);
}
public Categorizer3()
{
}
private Feature2D create_FeatureDetector()
{
return new SURF(500);
//return new KAZE();
//return new SIFT();
//return new Freak();
}
private BOWImgDescriptorExtractor create_bowDescriptorExtractor(Feature2D descriptorExtractor)
{
LinearIndexParams ip = new LinearIndexParams();
SearchParams sp = new SearchParams();
var descriptorMatcher = new FlannBasedMatcher(ip, sp);
return new BOWImgDescriptorExtractor(descriptorExtractor, descriptorMatcher);
}
private void init(out Feature2D descriptorExtractor, out Feature2D featureDetector, out List<Mat> templates, out BOWKMeansTrainer bowtrainer, out BOWImgDescriptorExtractor bowDescriptorExtractor)
{
int clusters = 1000;
featureDetector = create_FeatureDetector();
MCvTermCriteria term = new MCvTermCriteria(10000, 0.0001d);
term.Type = TermCritType.Iter | TermCritType.Eps;
bowtrainer = new BOWKMeansTrainer(clusters, term, 5, Emgu.CV.CvEnum.KMeansInitType.PPCenters);//****
BFMatcher matcher = new BFMatcher(DistanceType.L1);//****
descriptorExtractor = featureDetector;//******
bowDescriptorExtractor = create_bowDescriptorExtractor(descriptorExtractor);
templates = new List<Mat>();
string TEMPLATE_FOLDER = "C:\\Emgu\\book\\practical-opencv\\code\\src\\chapter8\\code8-5\\data\\templates";
//string TEMPLATE_FOLDER = "C:\\Emgu\\book\\practical-opencv\\code\\src\\chapter8\\code8-5\\data\\train_images";
foreach (var filename in Directory.GetFiles(TEMPLATE_FOLDER, "*", SearchOption.AllDirectories))
{
templates.Add(GetMat(filename, true));
this.OnTrained(filename);
}
}
void make_train_set(out List<Tuple<string, Mat>> train_set, out List<string> category_names)
{
string TRAIN_FOLDER = "C:\\Emgu\\book\\practical-opencv\\code\\src\\chapter8\\code8-5\\data\\train_images";
category_names = new List<string>();
train_set = new List<Tuple<string, Mat>>();
foreach (var dir in Directory.GetDirectories(TRAIN_FOLDER))
{
// Get category name from name of the folder
string category = new DirectoryInfo(dir).Name;
category_names.Add(category);
foreach (var filename in Directory.GetFiles(dir))
{
train_set.Add(new Tuple<string, Mat>(category, GetMat(filename, true)));
this.OnTrained(filename);
}
}
}
void build_vocab(Feature2D descriptorExtractor, Feature2D featureDetector, List<Mat> templates, BOWKMeansTrainer bowtrainer, out Mat vocab)
{
Mat vocab_descriptors = new Mat();
foreach (Mat templ in templates)
{
Mat desc = new Mat();
VectorOfKeyPoint kp = new VectorOfKeyPoint(featureDetector.Detect(templ));
descriptorExtractor.Compute(templ, kp, desc);
vocab_descriptors.PushBack(desc);
}
bowtrainer.Add(vocab_descriptors);
vocab = new Mat();
bowtrainer.Cluster(vocab);
string fn = getVocabularyFileName();
using (FileStorage fs = new FileStorage(fn, FileStorage.Mode.Write))
{
fs.Write(vocab, "vocab");
fs.ReleaseAndGetString();
}
}
void make_pos_neg(List<Tuple<string, Mat>> train_set, BOWImgDescriptorExtractor bowDescriptorExtractor, Feature2D featureDetector, List<string> category_names,
out Dictionary<string, Mat> positive_data, out Dictionary<string, Mat> negative_data)
{
positive_data = new Dictionary<string, Mat>();
negative_data = new Dictionary<string, Mat>();
foreach (var tu in train_set)
{
string category = tu.Item1;
Mat im = tu.Item2;
Mat feat = new Mat();
VectorOfKeyPoint kp = new VectorOfKeyPoint(featureDetector.Detect(im));
bowDescriptorExtractor.Compute(im, kp, feat);
for (int cat_index = 0; cat_index < category_names.Count; cat_index++)
{
string check_category = category_names[cat_index];
if (check_category.CompareTo(category) == 0)
{
if (!positive_data.ContainsKey(check_category))
positive_data[check_category] = new Mat();
positive_data[check_category].PushBack(feat);
}
else
{
if (!negative_data.ContainsKey(check_category))
negative_data[check_category] = new Mat();
negative_data[check_category].PushBack(feat);
}
}
}
}
void train_classifiers(List<string> category_names, Dictionary<string, Mat> positive_data, Dictionary<string, Mat> negative_data)
{
for (int i = 0; i < category_names.Count; i++)
{
string category = category_names[i];
// Postive training data has labels 1
Mat train_data = positive_data[category];
Mat train_labels = new Mat(train_data.Rows, 1, DepthType.Cv32S, 1);
{
for (int col = 0; col < train_labels.Cols; col++)
for (int row = 0; row < train_labels.Rows; row++)
train_labels.SetValue(row, col, (int)1);
train_labels.SetTo(new MCvScalar(1));
// Negative training data has labels 0
train_data.PushBack(negative_data[category]);
Mat m = new Mat(negative_data[category].Rows, 1, DepthType.Cv32S, 1);
{
for (int col = 0; col < m.Cols; col++)
for (int row = 0; row < m.Rows; row++)
m.SetValue(row, col, (int)0);
m.SetTo(new MCvScalar(0));
train_labels.PushBack(m);
}
SVM svm = new SVM();
svm.C = 312.5;
svm.Gamma = 0.50625000000000009;
svm.SetKernel(SVM.SvmKernelType.Rbf);
svm.Type = SVM.SvmType.CSvc;
svm.Train(train_data, Emgu.CV.ML.MlEnum.DataLayoutType.RowSample, train_labels);
var fn = getSVMFileName(category);
svm.SaveSVMToFile(fn);
notFromFile[category] = svm;
}
}
}
Dictionary<string, SVM> notFromFile = new Dictionary<string, SVM>();//****
private void initDir()
{
var dir = getSaveDir();
if (Directory.Exists(dir))
foreach (var fn in Directory.GetFiles(dir))
File.Delete(fn);
}
private string getSaveDir()
{
string dir = Path.Combine(Path.GetTempPath(), "Dece", "SVMS");
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
return dir;
}
private string getSVMFileName(string category)
{
return Path.Combine(getSaveDir(), category + ".svm");
}
private string getVocabularyFileName()
{
return Path.Combine(getSaveDir(), "vocabulary.voc");
}
//[HandleProcessCorruptedStateExceptions]
public IEnumerable<ImageInfo> Categorize(IEnumerable<string> imageFileNames)
{
var featureDetector = create_FeatureDetector();
var bowDescriptorExtractor = create_bowDescriptorExtractor(featureDetector);
Mat vocab = new Mat();
using (var fs = new FileStorage(getVocabularyFileName(), FileStorage.Mode.Read))
fs["vocab"].ReadMat(vocab);
bowDescriptorExtractor.SetVocabulary(vocab);
Dictionary<string, string> svms = new Dictionary<string, string>();
foreach (var xml in Directory.GetFiles(getSaveDir(), "*.svm"))
svms.Add(Path.GetFileNameWithoutExtension(xml), xml);
Dictionary<string, SVM> dic = new Dictionary<string, SVM>();
foreach (var fn in imageFileNames)
{
string scoreTxt = Environment.NewLine;
float score = float.MaxValue;
//float score = float.MinValue;
string cat = "";
try
{
using (Mat frame_g = GetMat(fn, false))
{
using (Mat img = new Mat())
{
VectorOfKeyPoint kp = new VectorOfKeyPoint(featureDetector.Detect(frame_g));
bowDescriptorExtractor.Compute(frame_g, kp, img);
foreach (var category in svms.Keys)
{
SVM svm = null;
if (!dic.ContainsKey(category))
{
string svmFn = svms[category];
svm = new SVM();
svm.LoadSVMFromFile(svmFn);
dic[category] = svm;
}
else
svm = dic[category];
svm = notFromFile[category];//*************
float classVal = svm.Predict(img, null);
float scoreVal = svm.Predict(img, null, 1);
//float signMul = (classVal < 0) == (scoreVal < 0) ? 1f : -1f;
//float score1 = signMul * scoreVal;
scoreTxt += string.Format("{0}-{1}: {2}{3}", category, classVal.ToString(), scoreVal.ToString("N3"), Environment.NewLine);
if (scoreVal < score)
{
score = scoreVal;
cat = category;
}
}
}
}
}
catch (Exception)
{
score = 0f;
cat = "hata";
}
if (string.IsNullOrEmpty(cat))
score = 0f;
yield return new ImageInfo(fn, cat, scoreTxt);
}
}
private static object matLocker = new object();
public Mat GetMat(string fn, bool train)
{
lock (matLocker)
{
var mat = new Mat(fn, ImreadModes.Color);
var mat2 = new Mat();
mat.ConvertTo(mat2, DepthType.Cv8U);
return mat2;
}
}
}

How to check if checkbox is selected?

I have little issue with checkbox added programmatically. I don't know how to check which checkbox are selected, when I hit "Send Button".
layout.RemoveAllViewsInLayout();
CheckBox _Options = new CheckBox(Activity);
ScrollView _Scroll = new ScrollView(Activity);
_Scroll.LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent);
LinearLayout _LScroll = new LinearLayout(Activity);
_LScroll.LayoutParameters = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent);
_LScroll.Orientation = Orientation.Vertical;
_LScroll.SetGravity(GravityFlags.CenterHorizontal);
//_Scroll.AddView(_LScroll);
Button _Send = new Button(Activity);
_Send.Text = "Wyƛlij";
_Send.LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent);
for (int i = 0; i < _Item.options.Length; i++)
{
_Options.Text = _Item.options[i];
_Options.Id = i;
_Options.LayoutParameters = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent);
_LScroll.AddView(_Options);
}
_Send.Click += delegate
{
_MultiAnswer._QuestionId = _Item.id;
for(int i = 0; i < _Item.options.Length; i++)
{
if (_Options.Selected == true)
{
_MultiAnswer._AnwserOptionIds.SetValue(i + 1, i);
}
}
output = JsonConvert.SerializeObject(_MultiAnswer);
SendJson(_Url, DataCache._Login, output);
SetLayout(layout, btn);
};
_Scroll.AddView(_LScroll);
layout.AddView(_Scroll);
layout.AddView(_Send);
I'll try to work on ID of checkbox, but I really don't know how to do it. I was thinking on method, which give me code which create checkbox, but still don't know how to check if checkbox is selected.
I understand that you've many checkbox controls. So add them to a list as follows:
List<Checkbox> checkboxes = new List<Checkbox>
{
chk1, chk2, chk3
};
When you want to know which ones are checked, you'll do this:
IEnumerable<Checkbox> checkedCheckboxes = checkboxes.Where(chk => chk.Checked);
This is a quick and dirty sample on how to generate dynamic cheboxes and retreive their state :
public class MainActivity : Activity
{
public class MyItem
{
public string[] options { get; set; }
public int id { get; set; }
}
public class MyMultiAnswer
{
public int _QuestionId { get; set; }
}
private List<CheckBox> _chkList = new List<CheckBox>();
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
var _Item = new MyItem() { options =new string [] { "aaa", "bbb", "ccc" }, id=0 };
var _MultiAnswer = new MyMultiAnswer() { _QuestionId = 0 };
ScrollView _Scroll = new ScrollView(this);
_Scroll.LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent);
LinearLayout _LScroll = new LinearLayout(this);
_LScroll.LayoutParameters = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent);
_LScroll.Orientation = Orientation.Vertical;
_LScroll.SetGravity(GravityFlags.CenterHorizontal);
TextView txView = new TextView(this);
//_Scroll.AddView(_LScroll);
Button _Send = new Button(this);
_Send.Text = "test";
_Send.LayoutParameters = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent);
for (int i = 0; i < _Item.options.Length; i++)
{
CheckBox _Options = new CheckBox(this);
_chkList.Add(_Options);
_Options.Text = _Item.options[i];
_Options.Id = i;
_Options.LayoutParameters = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MatchParent, ViewGroup.LayoutParams.WrapContent);
_LScroll.AddView(_Options);
}
_Send.Click += delegate
{
_MultiAnswer._QuestionId = _Item.id;
string strChkIds = "";
foreach (var chk in _chkList.Where(c => c.Checked))
{
//_MultiAnswer._AnwserOptionIds.SetValue(_Options.Id + 1, _Options.Id);
//do something
strChkIds += " - " + chk.Id;
}
// or
for (int i = 0; i < _Item.options.Length; i++)
{
if (_chkList[i].Checked == true)
{
//_MultiAnswer._AnwserOptionIds.SetValue(i + 1, i);
//do something
}
}
//output = JsonConvert.SerializeObject(_MultiAnswer);
//SendJson(_Url, DataCache._Login, output);
//SetLayout(layout, btn);
txView.Text = "selected ids " + strChkIds;
};
_Scroll.AddView(_LScroll);
_LScroll.AddView(_Send);
_LScroll.AddView(txView);
// Set our view from the "main" layout resource
SetContentView(_Scroll);
}
}
This is a sample about how you can achieve this in a minimum effort.

Replace Images at the Top of ImageList and ListView

I will load say 10 images in imagelist and list View. then later, I want to replace the first 5 (top 5 in the list). But The new images are always added at the bottom of the list in the display.
Initialize_ListView()
for (int i = 0; i < 10; i++)
{
AddItemTo_ListView(i);
}
Now I later use this code to replace the top 5
for (int i = 0; i < 5; i++)
{
ImageAndThumb imgObj = new ImageAndThumb(output);
Replace(imgObj , i)
}
private void Initialize_ListView()
{
this.imageList1.Images.Clear();
this.listView1.Clear();
this.listView1.View = View.SmallIcon;
this.imageList1.ImageSize = new Size(75, 80);
this.listView1.SmallImageList = this.imageList1;
}
private void AddItemTo_ListView(int index)
{
ImageAndThumb imgObj = new ImageAndThumb(output);
ImageAndThumbLst.Add(imgObj);
this.imageList1.Images.Add(ImageAndThumbLst[index].Thumb);
ListViewItem item = new ListViewItem();
item.ImageIndex = index;
this.listView1.Items.Add(item);
}
private void Replace(ImageAndThumb obj, int indx)
{
ImageAndThumbLst[indx] = obj;
this.imageList1.Images[indx] = ImageAndThumbLst[indx].Thumb;
ListViewItem item = new ListViewItem();
item.ImageIndex = indx;
this.listView1.Items[indx]=item;
}
For anyone making the same mistake, I was creating a new item in he replace function which is unnecessay. The new replace function should look like this
private void Replace(ImageAndThumb obj, int indx)
{
ImageAndThumbLst[indx] = obj;
this.imageList1.Images[indx] = ImageAndThumbLst[indx].Thumb;
listView1.Refresh();
}

What C# template engine that has clean separation between HTML and control code?

What C# template engine
that uses 'pure' HTML having only text and markers
sans any control flow like if, while, loop or expressions,
separating html from control code ?
Below is the example phone book list code,
expressing how this should be done:
string html=#"
<html><head><title>#title</title></head>
<body>
<table>
<tr>
<td> id</td> <td> name</td> <td> sex</td> <td>phones</td>
</tr><!--#contacts:-->
<tr>
<td>#id</td> <td>#name</td> <td>#sex</td>
<td>
<!--#phones:-->#phone <br/>
<!--:#phones-->
</td>
</tr><!--:#contacts-->
</table>
</body>
</html>";
var contacts = from c in db.contacts select c;
Marker m = new Marker(html);
Filler t = m.Mark("title");
t.Set("Phone book");
Filler c = m.Mark("contacts", "id,name,sex");
// **foreach** expressed in code, not in html
foreach(var contact in contacts) {
int id = contact.id;
c.Add(id, contact.name, contact.sex);
Filler p = c.Mark("phones", "phone");
var phones = from ph in db.phones
where ph.id == id
select new {ph.phone};
if (phones.Any()) {
foreach(var ph in phones) {
p.Add(ph);
}
} else {
fp.Clear();
}
}
Console.Out.WriteLine(m.Get());
Use this code:
Templet.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
namespace templaten.com.Templaten
{
public class tRange
{
public int head, toe;
public tRange(int _head, int _toe)
{
head = _head;
toe = _toe;
}
}
public enum AType
{
VALUE = 0,
NAME = 1,
OPEN = 2,
CLOSE = 3,
GROUP = 4
}
public class Atom
{
private AType kin;
private string tag;
private object data;
private List<Atom> bag;
public Atom(string _tag = "",
AType _kin = AType.VALUE,
object _data = null)
{
tag = _tag;
if (String.IsNullOrEmpty(_tag))
_kin = AType.GROUP;
kin = _kin;
if (_kin == AType.GROUP)
bag = new List<Atom>();
else
bag = null;
data = _data;
}
public AType Kin
{
get { return kin; }
}
public string Tag
{
get { return tag; }
set { tag = value; }
}
public List<Atom> Bag
{
get { return bag; }
}
public object Data
{
get { return data; }
set { data = value; }
}
public int Add(string _tag = "",
AType _kin = AType.VALUE,
object _data = null)
{
if (bag != null)
{
bag.Add(new Atom(_tag, _kin, _data));
return bag.Count - 1;
}
else
{
return -1;
}
}
}
public class Templet
{
private string content;
string namepat = "\\w+";
string justName = "(\\w+)";
string namePre = "#";
string namePost = "";
string comment0 = "\\<!--\\s*";
string comment1 = "\\s*--\\>";
private Atom tokens; // parsed contents
private Dictionary<string, int> iNames; // name index
private Dictionary<string, tRange> iGroups; // groups index
private Atom buffer; // output buffer
private Dictionary<string, int> _iname; // output name index
private Dictionary<string, tRange> _igroup; // output index
public Templet(string Content = null)
{
Init(Content);
}
private int[] mark(string[] names, string group)
{
if (names == null || names.Length < 1) return null;
tRange t = new tRange(0, buffer.Bag.Count - 1);
if (group != null)
{
if (!_igroup.ContainsKey(group)) return null;
t = _igroup[group];
}
int[] marks = new int[names.Length];
for (int i = 0; i < marks.Length; i++)
marks[i] = -1;
for (int i = t.head; i <= t.toe; i++)
{
if (buffer.Bag[i].Kin == AType.NAME)
{
for (int j = 0; j < names.Length; j++)
{
if (String.Compare(
names[j],
buffer.Bag[i].Tag,
true) == 0)
{
marks[j] = i;
break;
}
}
}
}
return marks;
}
public Filler Mark(string group, string names)
{
Filler f = new Filler(this, names);
f.di = mark(f.names, group);
f.Group = group;
tRange t = null;
if (_igroup.ContainsKey(group)) t = _igroup[group];
f.Range = t;
return f;
}
public Filler Mark(string names)
{
Filler f = new Filler(this, names);
f.di = mark(f.names, null);
f.Group = "";
f.Range = null;
return f;
}
public void Set(int[] locations, object[] x)
{
int j = Math.Min(x.Length, locations.Length);
for (int i = 0; i < j; i++)
{
int l = locations[i];
if ((l >= 0) && (buffer.Bag[l] != null))
buffer.Bag[l].Data = x[i];
}
}
public void New(string group, int seq = 0)
{
// place new group copied from old group just below it
if (!( iGroups.ContainsKey(group)
&& _igroup.ContainsKey(group)
&& seq > 0)) return;
tRange newT = null;
tRange t = iGroups[group];
int beginRange = _igroup[group].toe + 1;
for (int i = t.head; i <= t.toe; i++)
{
buffer.Bag.Insert(beginRange,
new Atom(tokens.Bag[i].Tag,
tokens.Bag[i].Kin,
tokens.Bag[i].Data));
beginRange++;
}
newT = new tRange(t.toe + 1, t.toe + (t.toe - t.head + 1));
// rename past group
string pastGroup = group + "_" + seq;
t = _igroup[group];
buffer.Bag[t.head].Tag = pastGroup;
buffer.Bag[t.toe].Tag = pastGroup;
_igroup[pastGroup] = t;
// change group indexes
_igroup[group] = newT;
}
public void ReMark(Filler f, string group)
{
if (!_igroup.ContainsKey(group)) return;
Map(buffer, _iname, _igroup);
f.di = mark(f.names, group);
f.Range = _igroup[group];
}
private static void Indexing(string aname,
AType kin,
int i,
Dictionary<string, int> dd,
Dictionary<string, tRange> gg)
{
switch (kin)
{
case AType.NAME: // index all names
dd[aname] = i;
break;
case AType.OPEN: // index all groups
if (!gg.ContainsKey(aname))
gg[aname] = new tRange(i, -1);
else
gg[aname].head = i;
break;
case AType.CLOSE:
if (!gg.ContainsKey(aname))
gg[aname] = new tRange(-1, i);
else
gg[aname].toe = i;
break;
default:
break;
}
}
private static void Map(Atom oo,
Dictionary<string, int> dd,
Dictionary<string, tRange> gg)
{
for (int i = 0; i < oo.Bag.Count; i++)
{
string aname = oo.Bag[i].Tag;
Indexing(oo.Bag[i].Tag, oo.Bag[i].Kin, i, dd, gg);
}
}
public void Init(string Content = null)
{
content = Content;
tokens = new Atom("", AType.GROUP);
iNames = new Dictionary<string, int>();
iGroups = new Dictionary<string, tRange>();
// parse content into tokens
string namePattern = namePre + namepat + namePost;
string patterns =
"(?<var>" + namePattern + ")|" +
"(?<head>" + comment0 + namePattern + ":" + comment1 + ")|" +
"(?<toe>" + comment0 + ":" + namePattern + comment1 + ")";
Regex jn = new Regex(justName, RegexOptions.Compiled);
Regex r = new Regex(patterns, RegexOptions.Compiled);
MatchCollection ms = r.Matches(content);
int pre = 0;
foreach (Match m in ms)
{
tokens.Add(content.Substring(pre, m.Index - pre));
int idx = -1;
if (m.Groups.Count >= 3)
{
string aname = "";
MatchCollection x = jn.Matches(m.Value);
if (x.Count > 0 && x[0].Groups.Count > 1)
aname = x[0].Groups[1].ToString();
AType t = AType.VALUE;
if (m.Groups[1].Length > 0) t = AType.NAME;
if (m.Groups[2].Length > 0) t = AType.OPEN;
if (m.Groups[3].Length > 0) t = AType.CLOSE;
if (aname.Length > 0)
{
tokens.Add(aname, t);
idx = tokens.Bag.Count - 1;
}
Indexing(aname, t, idx, iNames, iGroups);
}
pre = m.Index + m.Length;
}
if (pre < content.Length)
tokens.Add(content.Substring(pre, content.Length - pre));
// copy tokens into buffer
buffer = new Atom("", AType.GROUP);
for (int i = 0; i < tokens.Bag.Count; i++)
buffer.Add(tokens.Bag[i].Tag, tokens.Bag[i].Kin);
// initialize index of output names
_iname = new Dictionary<string, int>();
foreach (string k in iNames.Keys)
_iname[k] = iNames[k];
// initialize index of output groups
_igroup = new Dictionary<string, tRange>();
foreach (string k in iGroups.Keys)
{
tRange t = iGroups[k];
_igroup[k] = new tRange(t.head, t.toe);
}
}
public string Get()
{
StringBuilder sb = new StringBuilder("");
for (int i = 0; i < buffer.Bag.Count; i++)
{
switch (buffer.Bag[i].Kin)
{
case AType.VALUE:
sb.Append(buffer.Bag[i].Tag);
break;
case AType.NAME:
sb.Append(buffer.Bag[i].Data);
break;
case AType.OPEN:
case AType.CLOSE:
break;
default: break;
}
}
return sb.ToString();
}
}
public class Filler
{
private Templet t = null;
public int[] di;
public string[] names;
public string Group { get; set; }
public tRange Range { get; set; }
private int seq = 0;
public Filler(Templet tl, string markers = null)
{
t = tl;
if (markers != null)
names = markers.Split(new char[] { ',' },
StringSplitOptions.RemoveEmptyEntries);
else
names = null;
}
public void init(int length)
{
di = new int[length];
for (int i = 0; i < length; i++)
di[i] = -1;
seq = 0;
Group = "";
Range = null;
}
// clear contents inside marked object or group
public void Clear()
{
object[] x = new object[di.Length];
for (int i = 0; i < di.Length; i++)
x[i] = null;
t.Set(di, x);
}
// set value for marked object,
// or add row to group and set value to columns
public void Set(params object[] x)
{
t.Set(di, x);
}
public void Add(params object[] x)
{
if (Group.Length > 0)
{
t.New(Group, seq);
++seq;
t.ReMark(this, Group);
}
t.Set(di, x);
}
}
}
Testing program
Program.cs
Templet m = new Templet(html);
Filler f= m.Mark("title");
f.Set("Phone book");
Filler fcontacts = m.Mark("contacts", "id,name,sex,phone");
fcontacts.Add(1, "Akhmad", "M", "123456");
fcontacts.Add(2, "Barry", "M", "234567");
fcontacts.Add(1, "Charles", "M", "345678");
Console.Out.WriteLine(m.Get());
Still can't do nested loop- yet.
Just use ASP.NET. Whether you use webforms or MVC, it's super easy to have C# in your .cs files, and HTML in your .aspx files.
As with anything in programming, it's 99% up to you to do things right. Flexible UI engines aren't going to enforce that you follow good coding practices.
In principle most any template engine you choose can separate HTML from control logic with the proper architecture. using an MVC (Or MVVM) pattern, if you construct your model in such a way that the controller contains the if/then logic instead of the view you can eliminate it from the view.
That said, the syntax you use is very close to Razor syntax which is easily available for ASP.NET MVC through NuGet packages.
I totally hear you. I built SharpFusion, which has some other stuff in it but if you look for the template.cs file you will see the handler that parses a HTML file and simply replaces out tokens with values that you've made in c#.
Because no XML parsing is done like ASP.NET the framework loads much faster than even an MVC site.
Another alternative is ServiceStack.

Categories

Resources