I have following code in C#, WPF:
base.DataContext = new DataTemplate[]
{
new DataTemplate
{
lblText = "First",
txtBoxContent = ""
},
new DataTemplate
{
lblText = "Second",
txtBoxContent = "Something"
}
};
but i need to fill DataContext dynamically from database. My idea looks like this:
base.DataContext = new DataTemplate[]
{
for(int i = 0; i< dsTmp.Tables[0].Rows.Count; i++)
{
new DataTemplate
{
lblText = "Count: ",
txtBoxContent = dsTmp.Tables[0].Rows[i][0].ToString();
}
}
};
When i type this, it yells some syntax errors on me;
Could anybody tell me, how to write it correctly?
You can't have code inside object initializer syntax. Why not simply do this:
var list = new DataTemplate[dsTmp.Tables[0].Rows.Count];
for(int i = 0; i< dsTmp.Tables[0].Rows.Count; i++)
{
var item = new DataTemplate
{
lblText = "Count: ",
txtBoxContent = dsTmp.Tables[0].Rows[i][0].ToString();
};
list[i] = item;
}
this.DataContext = list;
MBen and Habib have already answered why the for is failing, because you can't do a loop in an object initializer and have provided loop alternatives.
Alternatively you can use linq to perform an initialization.
this.DataContext=dsTmp.Tables[0].Rows.Select(
x=>new DataTemplate {
lblText = "Count: ",
txtBoxContent=x[0].ToString()
}).ToArray();
The error that ; is missing is bit misleading. The actual problem is that you are trying to create an array of DataTemplate with the loop, You can't use loop in array/object initialization. Try the following.
DataTemplate[] tempDataTemplate = new DataTemplate[ds.Temp.Tables[0].Rows.Count]();
for(int i = 0; i< dsTmp.Tables[0].Rows.Count; i++)
{
tempDataTemplate[i] = new DataTemplate
{
lblText = "Count: ",
txtBoxContent = dsTmp.Tables[0].Rows[i][0].ToString();
};
}
base.DataContext = tempDataTemplate;
i dont know what you wanna achieve, but did you ever try mvvm with viewmodel first approach?
create a viewmodel class, e.g. MyData with 2 public properties MyText, MyContent. create a collection of these objects and fill this from your database.
at least you need an itemscontrol with itemssource binding set to your collection and a datatemplate for your MyData object.
<DataTemplate DataType="{x:Type local:MyData}">
<view:MyDataViewControl />
</DataTemplate>
now you see all your dynamic objects in your itemscontrol.
Related
I. This is the part of the code in the C# form
this.cbDay.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.cbDay.FormattingEnabled = true;
this.cbDay.Items.AddRange(new object[] {
});//items from a loop in another class and method.
II. This is my method in another class
namespace StudentRegistrationApplication
public class loopComboBoxSelection
{
public loopComboBox(int start, int finsh)
{
for (int i = start; i < finsh; i++)
{
ComboboxItem item = new ComboboxItem();
item.Text = "Item " + i;
item.Value = i;
ModDown.Items.Add(item);
}
}
}
III. I want to call the loop method that will generate items from 1 to 100. For this question, what is the syntax?
this.cbDay.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.cbDay.FormattingEnabled = true;
this.cbDay.Items.AddRange(new object[] {
"1"
"2"
"3"
"4"
"5"});
You're doing it wrong. You should be binding the data to the ComboBox, e.g.
cbDay.DisplayMember = nameof(ComboBoxItem.Text);
cbDay.ValueMember = nameof(ComboBoxItem.Value);
cbDay.DataSource = Enumerable.Range(startValue, endValue - startValue + 1)
.Select(i => new ComboBoxItem {Text = $"Item {i}", Value = i})
.ToArray();
The Text values will then be displayed in the control and, when the user makes a selection, you can get the corresponding Value from the SelectedValue property of the control.
Note that you don't have to use LINQ to create the list but it's the binding part that's important. By setting the DataSource, you're able to get a specific property value from the SelectedValue rather than just the same as you'd get from SelectedItem.
I have done the following code and works well. I am wondering how I can do a for loop to clean this code from 38 lines into 2 lines.
s0s.Text = seg[0].start.ToString("X8");
s0e.Text = seg[0].end.ToString("X8");
s1s.Text = seg[1].start.ToString("X8");
s1e.Text = seg[1].end.ToString("X8");
// .. many more ..
s19s.Text = seg[19].start.ToString("X8");
s19e.Text = seg[19].end.ToString("X8");
I can obviously do the seg[i] substitution, but how do i do it with the text boxes?
I suppose you could use the Controls property and call OfType<T>() to get all the instances of TextBoxes in your Form instance
Filters the elements of an IEnumerable based on a specified type.
Then convert the results to a Dictionary based on the control Name
// this could potentially be done in the constructor
var dict = Controls.OfType<TextBox>().ToDictionary(x => x.Name);
for (int i = 0; i < 19; i++)
{
dict[$"s{i}s"].Text = $"{seg[i].Start:X8}";
dict[$"s{i}e"].Text = $"{seg[i].End:X8}";
}
Note : This code is untested and only a guide to a possible solution
I'd be tempted to do it this way. First create two lists of your controls, the starts and the ends:
var starts = new List<TextBox>
{
s0s,
s1s,
//...
s19s
};
var ends = new List<TextBox>
{
s0e,
s1e,
//...
s19e
};
Then loop over each list:
var i = 0;
foreach (var start in starts)
{
start.Text = seg[i].start.ToString("X8");
++i;
}
i = 0;
foreach (var end in ends)
{
start.Text = seg[i].end.ToString("X8");
++i;
}
Your indexes and control numbers would need to line up perfectly though.
Note: Like TheGeneral's code, this is untested (neither of us wants to create a form with 38 text boxes with specific names)
Based on the textboxes names I would suggest alternative approach to use control designed to display collection of things - DataGridView would be one of the options.
With data binding you can achieve little bit more maintainable code
public class MyItem
{
public int Start { get; set; }
public int End { get; set; }
}
In the form create a datagridview with two bounded columns, you can do this in winforms designer without manually writing the code below.
// constructor
public MyForm()
{
var startColumn = new DataGridViewTextBoxColumn();
startColumn.DataPropertyName = "Start"; // Name of the property in MyItem class
startColumn.DefaultCellStyle.Format = "X8";
var endColumn = new DataGridViewTextBoxColumn();
endColumn.DataPropertyName = "End"; // Name of the property in MyItem class
endColumn.DefaultCellStyle.Format = "X8";
myDataGridView.Columns.AddRange(startColumn, endColumn);
myDataGridView.AutoGenerateColumns = false;
}
private void Form1_Load(object sender, EventArgs e)
{
var items = new List<MyItem>
{
new MyItem { Start = 10, End = 20 },
new MyItem { Start = 11, End = 19 },
new MyItem { Start = 12, End = 18 }
};
myDataGridView.DataSource = items;
}
firstly when you create they variables insert them all to an array. then run a loop as following:
for (int i; int < 19(your list); i++)
{
your list[i].Text = seg[i].start.ToString("X8");
your list[i].Text = seg[i].end.ToString("X8");
}
I have ListView that is dynamic and Columns name need to change dynamic so i create this:
var gridView = new GridView();
this.lvWorkers.View = gridView;
foreach(string c in columnName)
{
gridView.Columns.Add(new GridViewColumn
{
Header = c.Remove(0, 5),
DisplayMemberBinding = new Binding(c)
});
}
Now i want add Items to this list but there is no SubItems like in Win Forms. I find similar problems, the answer was to make class that is defined. Add Items to Columns in a WPF ListView
I need to add Items dynamic.
Win Forms which is not work.
foreach (OneStudentEvent e in oneEventList)
{
ListViewItem item = new ListViewItem(e.Indeks.ToString());
item.SubItems.Add(e.eventString);
...
lvWorkers.Items.Add(item);
}
EDIT
Now i remove DisplayMemberBinding = new Binding(c)
and add:
lvWorkers.ItemsSource = getList();
private ArrayList getList()
{
ArrayList data = new ArrayList();
for(int i=0; i<20; i++)
{
List<string> tempList = new List<string>();
for(int j = 0; j < 30; j++)
{
tempList.Add(j.ToString());
}
data.Add(tempList);
}
return data;
}
And i don't see string in list but word: (Collection). I know that this is my bad to show collection no single string, but i don't know hot to make it.
I have a list of result listed after extracting from a .txt file. I would like to add a checkbox behind every results listed. The following is my code:
private void LoadFile() {
List<string> lines = new List<string>();
try
{
StreamReader sr = new StreamReader("test.txt");
while (!sr.EndOfStream)
{
lines.Add(sr.ReadLine());
}
sr.Close();
for (int i = 3; i < lines.Count; i++)
{
resultsTreeView.Items.Add(lines[i].ToString().Substring(67,17));
resultsTreeView.Items.Add(CheckBox[i]);
}
How can I add checkboxes as the results extracted will change every time? I would like to track which boxes has checked as well so that I can print the result to users. Thank you!
for (int i = 3; i < lines.Count; i++)
{
resultsTreeView.Items.Add(lines[i].ToString().Substring(67,17));
resultsTreeView.Items.Add(new CheckBox());
// resultsTreeView.Items.Add(BuildCheckBox())
}
OR
CheckBox BuildCheckbox()
{
CheckBox C = new CheckBox();
return C;
}
That's all you need to create a checkbox, or you can create a function that returns a checkbox, inside it you create a new instance of checkbox and set the attributes/subscribe to events the way you want and return it.
As for the tracking which checkboxes are checked, I only need you to provide me with the type of your "resultsTreeView"
EDIT :
To loop through checkboxes in the TreeView and do something on the checked ones:
resultsTreeView.Items.OfType<CheckBox>().ToList()
.ForEach(C =>
{
if (C.IsChecked.HasValue && C.IsChecked.Value == true)
{
//DoSomething
}
});
I am not sure exactly what you are looking for. I assume resultsTreeView is a TreeViewItem. and I also assume that you are working in wpf. You can do the following through wpf.
for (int i = 0; i < lines.Count(); i++)
{
resultsTreeView.Items.Add(lines[i].ToString().Substring(67,17));
}
<TreeView x:Name="resultsTreeView" HorizontalAlignment="Left" Height="100" Margin="37,344,0,0" VerticalAlignment="Top" Width="257" >
<TreeView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding}"/>
<CheckBox/>
</StackPanel>
</DataTemplate>
</TreeView.ItemTemplate>
</TreeView>
Something similar could be done through code behind
for (int i = 0; i < mylist.Count(); i++)
{
resultsTreeView.Items.Add(mylist[i]);
}
resultsTreeView.ItemTemplate = TreeViewDataTemp;
And then create TreeViewDataTemp the following way
private static DataTemplate TreeViewDataTemp
{
get
{
DataTemplate TVDT = new DataTemplate();
FrameworkElementFactory Stack = new FrameworkElementFactory(typeof(StackPanel));
Stack.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal);
FrameworkElementFactory TextB = new FrameworkElementFactory(typeof(TextBlock));
TextB.SetValue(TextBlock.TextProperty, new Binding());
FrameworkElementFactory ChkBox = new FrameworkElementFactory(typeof(CheckBox));
Stack.AppendChild(TextB);
Stack.AppendChild(ChkBox);
TVDT.VisualTree = Stack;
return TVDT;
}
}
The above gives you 1 item which is text together with a checkbox.
Alternatively your method will add a checkbox as a new item after every string item that you add.. which is
for (int I=0; I<lines.Count(); I++)
{
resultsTreeView.Items.Add(mylist[i]);
resultsTreeView.Items.Add(new CheckBox());
}
I am trying to do something like this:
for (int i = 1; i < nCounter ; i++)
{
string dvName = "dv" + i.ToString();
System.Windows.Forms.DataGridView dvName = new DataGridView();
// other operations will go here..
}
As you can guess, what I am trying to do is at i == 1, create a DataGridView with name dv1, and at i == 2, create a DataGridView with name dv2, but I can't.
Visual studio squiggles saying "a local variable named dvName is already delared in this scope" I also tried the following:
for (int i = 1; i <nCounter ; i++)
{
System.Windows.Forms.DataGridView dv & i = new DataGridView();
// other operations will go here..
}
But VS squiggles again, I hope you understood what I am trying to accomplish. Can anyone suggest how can I do this?
What you really need is a Dictionary<int, DataGridView> grids. Populate it in your for loop (grids[i] = new DataGridView();) and then, later, use the required grid (grids[someCalculatedIndex])
Hope this helps.
try a data structure where you can hold your variables eg dict etc
System.Collections.Generic.Dictionary<string,System.Windows.Forms.DataGridView>
grids = new Dictionary<string,System.Windows.Forms.DataGridView>();
for (int i = 1; i <nCounter ; i++)
{
grids.Add("dv" + i.ToString(), new DataGridView());
}
// to work on grid 1
DataGridView grid1 = grids["dv1"];
// so on
So your are trying to create the variable name dynamically? That's not possible. Why not use an Array or a List (or even a Dictionary)? Or do you want to just set the name of the control?
var list = new List<DataGridView>();
for (int i = 1; i <nCounter ; i++)
{
System.Windows.Forms.DataGridView dvName = new DataGridView();
dvName.Name = "dv" + i.ToString();
list.Add(dvName);
// other operations will go here..
}
foreach (var dv in list)
{
...do something...
}
DataGridView secondDv = list.Single(dv=>dv.Name == "dv2");
secondDv.DoSomething()
Not clear want you want to do...