Here is my code for binding a dictionary item to a Chart control. I keep getting the following error:
"Index was out of range. Must be non-negative and less than the size of the collection. Parameter name: index"
Here is my Code:
foreach (DataRow drow in objD0s.Tables[0].Rows)// Adding values from a dataset to dictionary
{
string strvalue = Convert.ToString(drow["Chemical Name"]);
string doublevalue = Convert.ToString(drow["Global Warming"]);
Cdata.Add(Convert.ToString(strvalue), Convert.ToDouble(doublevalue));
}
ColumnSeries colSeries = ChartChemImpact.Series[0] as ColumnSeries;
((ColumnSeries)ChartChemImpact.Series[0]).DataContext = Cdata;
colSeries.ItemsSource = myDataTable0.DefaultView;
colSeries.IndependentValueBinding = new Binding("[Chemical Name]");
colSeries.DependentValueBinding = new Binding("[Global Warming]");
}
XAM
chartingToolkit:Chart Name="ChartChemImpact" Title="Chart Title" Width="384" Height="280">
<chartingToolkit:ColumnSeries DependentValuePath="Key" IndependentValuePath="Value" ItemsSource="{Binding}" Name="colSeries" />
</chartingToolkit:Chart>
Please help :(
Ok, I have found the mistake. There are binding and value paths in the xaml, but they are replaced in the code.
I would remove those lines, so here is the result:
foreach (DataRow drow in objD0s.Tables[0].Rows)// Adding values from a dataset to dictionary
{
string strvalue = Convert.ToString(drow["Chemical Name"]);
string doublevalue = Convert.ToString(drow["Global Warming"]);
Cdata.Add(Convert.ToString(strvalue), Convert.ToDouble(doublevalue));
}
((ColumnSeries)ChartChemImpact.Series[0]).DataContext = Cdata;
//And that's the end of the function, no more code
}
Related
My wpf app xaml is simple, only a datagrid:
<DataGrid ItemsSource="{Binding UserCollection}"/>
In code behind, UserCollection is a DataTable:
private DataTable userCollection;
public DataTable UserCollection
{
get { return this.userCollection; }
set
{
this.userCollection = value;
NotifyPropertyChanged();
}
}
In ViewModel.cs, code is simple, create 2 columns and add a row:
this.UserCollection = new DataTable();
UserCollection.Columns.Add("col1", typeof(int));
UserCollection.Columns.Add("co.l2", typeof(int));
var r=UserCollection.NewRow();
r["col1"] = 1;
r["co.l2"] = 2;
UserCollection.Rows.Add(r);
But the 2nd column which hearder contains a dot cannot display the value in UI, you can see the picture.
Why?
I have found the solution, replace dot char to another char by using :
StringNameWithDot.Replace(".", "\x2024");
Wpf datatable column header cannot contain ".","/","[]", here is another link:
What is it about DataTable Column Names with dots that makes them unsuitable for WPF's DataGrid control?
Greetings! I am very new to WPF. I have a simple need i guess. I need to display eachline of textfile in datagrid. number of lines in file are not know before.
i am using streamreader to reader the line from text file.
when i am trying to add the content to new row, a new row is getting added but with no content.
grid1.items.add(t) 'where t is the line read from the text file
i think t to be items, i do know how to add items and add content to it. Your help is highly appreciated.
Thanks a ton in advance.
sri
System.IO.StreamReader file = new System.IO.StreamReader("filename.txt");
string[] columnnames = file.ReadLine().Split(' ');
DataTable dt = new DataTable();
foreach (string c in columnnames)
{
dt.Columns.Add(c);
}
string newline;
while ((newline = file.ReadLine()) != null)
{
DataRow dr = dt.NewRow();
string[] values = newline.Split(' ');
for (int i = 0; i < values.Length; i++)
{
dr[i] = values[i];
}
dt.Rows.Add(dr);
}
file.Close();
dataGridView1.DataSource = dt;
Try this
Adding columns and setting proper Binding is must.
Everything in code :
string[] lines = {"line1", "line2" };
DataGridTextColumn col1 = new DataGridTextColumn();
Dgrd.Columns.Add(col1);
col1.Binding = new Binding(".");
Dgrd.Items.Add(lines[0]);
Adding column in XAML :
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding .}"/>
</DataGrid.Columns>
Without directly Items.Add :
string[] lines = { "line1", "line2" };
Dgrd.ItemsSource = lines.ToList();
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding .}"/>
</DataGrid.Columns>
I am trying to populate a WPF datagrid but it's only showing the column headers and the content cells of the first(!) column. All other cells are empty:
The DataGrid is defined like this:
<DataGrid ItemsSource="{Binding Classifications, Mode=OneWay}"
AutoGenerateColumns="True" HeadersVisibility="Column" />
Classifications is defined in the code-behind file like this:
public DataView Classifications
{
get
{
return ClassificationDataTable.GetTable(myData).DefaultView
}
}
and finally this is my data generator:
public static class ClassificationDataTable
{
public static DataTable GetTable(List<Classification> classifications)
{
DataTable table = new DataTable();
// build columns
table.Columns.Add("FruitPrototype", typeof (string));
foreach (var featureComparison in classifications[0].FeatureComparisons)
table.Columns.Add(featureComparison.FeatureName, typeof (double));
// add rows
foreach (var classification in classifications)
{
object[] values = new object[classification.FeatureComparisons.Count+1];
values[0] = classification.FruitPrototype.FruitType;
for (int i = 0; i < classification.FeatureComparisons.Count; i++)
values[i + 1] = classification.FeatureComparisons[i].NormalizedDistance;
table.Rows.Add(values);
}
return table;
}
}
I verified the binding and can confirm that the DefaultView of the DataTable is indeed bound to the ItemsSource of my DataGrid. Also, the double values that should be shown in the grid are != 0.
What am I missing here?
I figured it out with the help of Jimmy W's question: I had some brackets and dots in the column names which somehow broke the binding of the cells. Changing the values of the feature names in
table.Columns.Add(featureComparison.FeatureName, typeof (double));
fixed my problem.
I have a WPF User Control with a ListView in it that is created based on the DataSet that is passed to it:
public void PopulateList(DataSet ds) {
listView.View = CreateGridViewColumns(ds.Tables[0]);
listData.DataContext = ds.Tables[0];
}
private GridView CreateGridViewColumns(DataTable dt) {
// Create the GridView
var gv = new GridView {AllowsColumnReorder = true};
// Create the GridView Columns
foreach (DataColumn item in dt.Columns) {
var gvc = new GridViewColumn
{
DisplayMemberBinding = new Binding(item.ColumnName),
Header = item.ColumnName,
Width = Double.NaN
};
gv.Columns.Add(gvc);
}
return gv;
}
Now I create the user control in code and call it's PopulateList with the appropriate dataset and this is where the problems are starting:
If I pass in a dataset that was created from a call to the database the list view shows all the data but if i pass in a DataSet that i created in code the ListView shows the Columns but will not show the data
//This is a function that hides the DB call return type is DataSet
var dsPatientSmokingStatusHistory = DataRepository.PatientSmokingStatusProvider.GetHistory(PatientId);
//radGridViewPatientSmokingStatus.DataSource = dsPatientSmokingStatusHistory.Tables[0];
var dt = new DataTable();
string c1 = "Date".PadLeft(23).PadRight(23);
string c2 = "Status".PadLeft(20).PadRight(50);
dt.Columns.Add(c1);
dt.Columns.Add(c2);
int i = 0;
foreach (DataRow row in dsPatientSmokingStatusHistory.Tables[0].Rows) {
var dataRow = dt.NewRow();
dataRow[c1] = ((DateTime)row["Date"]).ToString("MM/dd/yyyy");
dataRow[c2] = row["Status"].ToString();
dt.Rows.Add(dataRow);
dt.Rows[i].AcceptChanges();
i++;
}
DataSet ds = new DataSet();
dt.TableName = "Table";
ds.Tables.Add(dt);
ds.AcceptChanges();
smokingStatusGrid.GridWidth = 455;
smokingStatusGrid.GridHight = 97;
//This line does not show data
smokingStatusGrid.PopulateGrid(ds);
//This line will show data
smokingStatusGrid.PopulateGrid(dsPatientSmokingStatusHistory);
Is there a difference between these two datasets that i don't know about that is preventing me from databinding to it?
Also the user control is being used as an ElementHost in a WinForms application (not sure if this makes a difference)
Your code says:
DisplayMemberBinding = new Binding(item.ColumnName)
This binding constructor takes a string paramter which as per MSDN is "The initial Path for the binding" and is of datatype System.Windows.PropertyPath. I guess, since system tries to find a property with the same name in your class, and your string (item.ColumnName) has spaces at start, it runs into a problem (properties can't start with a space).
Would recommend you to take off the padding that you are doing in column name of your table. Apply any padding/margins in the Header of your GridView.
I have been confused while setting SelectedItem programmaticaly in wpf applications with Net Framework 3.5 sp1 installed. I have carefully read about hundred posts \topics but still confused((
My xaml:
<ComboBox name="cbTheme">
<ComboBoxItem>Sunrise theme</ComboBoxItem>
<ComboBoxItem>Sunset theme</ComboBoxItem>
</ComboBox>
If I add IsSelected="True" property in one of the items - it's dosn't sets this item selected. WHY ?
And i was try different in code and still can't set selected item:
cbTheme.SelectedItem=cbTheme.Items.GetItemAt(1); //dosn't work
cbTheme.Text = "Sunrise theme"; //dosn't work
cbTheme.Text = cbTheme.Items.GetItemAt(1).ToString();//dosn't work
cbTheme.SelectedValue = ...//dosn't work
cbTheme.SelectedValuePath = .. //dosn't work
//and even this dosn't work:
ComboBoxItem selcbi = (ComboBoxItem)cbTheme.Items.GetItemAt(1);//or selcbi = new ComboBoxItem
cbTheme.SelectedItem = selcbi;
The SelectedItem is not readonly property, so why it wan't work?
I think thats should be a Microsoft's problems, not my. Or I have missed something??? I have try playing with ListBox, and all work fine with same code, I can set selections, get selections and so on.... So what can I do with ComboBox ? Maybe some tricks ???
To select any item in the ComboBox and to set it as default item selected just use the below line:
combobox.SelectedIndex = 0; //index should be the index of item which you want to be selected
If i add the combobox and items programmatically, this works for me:
ComboBox newCombo = new ComboBox();
ComboBoxItem newitem = new ComboBoxItem();
newitem.Content = "test 1";
newCombo.Items.Add(newitem);
newitem = new ComboBoxItem();
newitem.Content = "test 2";
newCombo.Items.Add(newitem);
newitem = new ComboBoxItem();
newitem.Content = "test 3";
newCombo.Items.Add(newitem);
newCombo.SelectedItem = ((ComboBoxItem)newCombo.Items[1]);
newCombo.Text = ((ComboBoxItem)newCombo.Items[1]).Content.ToString();
newStack.Children.Add(newCombo);
It also works if it set the ItemSource property programmatically, then set the text to the selected value.
Create a public property in your viewmodel for the theme list and one for the selected item:
private IEnumerable<string> _themeList;
public IEnumerable<string> ThemeList
{
get { return _themeList; }
set
{
_themeList = value;
PropertyChangedEvent.Notify(this, "ThemeList");
}
}
private string _selectedItem;
public string SelectedItem
{
get { return _selectedItem; }
set
{
_selectedItem = value;
PropertyChangedEvent.Notify(this,"SelectedItem");
}
}
bind your combobox in xaml to the properties like this:
<ComboBox
Name="cbTheme"
ItemsSource="{Binding ThemeList}"
SelectedItem="{Binding SelectedItem}">
</ComboBox>
now all you do is add items to the ThemeList to populate the combobox. To select an item in the list, set the selected property to the text of the item you want selected like this:
var tmpList = new List<string>();
tmpList.Add("Sunrise theme");
tmpList.Add("Sunset theme");
_viewModel.ThemeList = tmpList;
_viewModel.SelectedItem = "Sunset theme";
or try setting the selected item to the string value of the item you want selected in your own code if you want to use the code you currently have - not sure if it will work but you can try.
If you know the index of the item you want to set, in this case it looks like you are trying to set index 1, you simply do:
cbTheme.SelectedIndex = 1;
I found that when you don't know the index, that's when you have the real issue. I know this goes beyond the original question, but for Googlers on that count that want to know how to set the item when the index isn't known but the value you want to display IS known, if you are filling your dropdown with an ItemSource from a DataTable, for example, you can get that index by doing this:
int matchedIndex = 0;
if (dt != null & dt.Rows != null)
{
if (dt.Rows.Count > 0)
{
foreach (DataRow dr in dt.Rows)
{
string myRowValue = dr["SOME_COLUMN"] != null ? dr["SOME_COLUMN"].ToString() : String.Empty;
if (myRowValue == "Value I Want To Set")
break;
else
matchedIndex++;
}
}
}
And then you do simply do cbTheme.SelectedIndex = matchedIndex;.
A similar iteration of ComboBoxItem items instead of DataRow rows could yield a similar result, if the ComboBox was filled how the OP shows, instead.
Is the ComboBox data bound?
If so you are probably better to do it through Binding rather than code ....
See this question ... WPF ListView Programmatically Select Item
Maybe create a new SelectableObject {Text = "Abc Theme", IsCurrentlySelected = True}
Bind a collection of SelectableObjects to the ComboBox.
Essentially setting the IsCurrentlySelected property in the model and having UI update from the Model.
Acording Answer 4
If you already add the Items in the Item source.
Fire the PropertyChangedEvent of the selectet Value.
tmpList.Add("Sunrise theme");
tmpList.Add("Sunset theme");
PropertyChangedEvent.Notify(this,"SelectedItem");