wpf toolkit datagrid performance - wpf

i am porting my application from windows forms to WPF. I have found that datagrid is available only through the WPF Toolkit. However i have some issues with performance. This could be because something that performed alright in windows forms does not in wpf since it has to be implemented differently. Anyhow, i am doing something like this:
// XAML
<toolkit:DataGrid x:Name="dataGrid" ItemsSource="{Binding Path=.}"/>
// C#
DataTable dataTable = new DataTable();
MyViewModel viewModel = new MyViewModel();
this.dataGrid.AutoGenerateColumns = false;
this.dataGrid.CanUserAddRows = false;
this.dataGrid.CanUserDeleteRows = false;
this.dataGrid.CanUserReorderColumns = true;
this.dataGrid.CanUserResizeColumns = true;
this.dataGrid.CanUserResizeRows = false;
this.dataGrid.CanUserSortColumns = true;
this.dataGrid.IsReadOnly = true;
this.dataGrid.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
this.dataGrid.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
this.dataGrid.ColumnHeaderHeight = 18;
this.dataGrid.RowHeight = 18;
this.dataGrid.DataContext = vm.dataGrid;
List<string> s = new List<string>();
for (int i = 0; i < 80; ++i)
{
s.Add("col" + i);
}
for (int i = 0; i < s.Count; ++i)
{
dataTable.Columns.Add(new DataColumn(s[i], typeof(string)));
Binding items = new Binding();
PropertyPath path = new PropertyPath(dataTable.Columns[i].ColumnName);
items.Path = path;
DataGridColumn dc = new DataGridTextColumn()
{
Header = dataTable.Columns[i].ColumnName,
Width=70,
Binding = items
};
this.dataGrid.Columns.Add(dc);
}
viewModel.dataGrid = dataTable;
this.dataGrid.DataContext = viewModel.dataGrid;
for (int i = 0; i < 1000; ++i)
{
var row = dataTable.NewRow();
for (int j = 0; j < s.Count; ++j)
{
row[s[j]] = "text" + s[j] + j;
}
dataTable.Rows.Add(row);
}
The above is a sample of simply generating same number of columns by binding each header.
When this loads, i get all the elements displayed correctly, but scrolling is really slow. I know that someone might say that i am rendering 80 columns and 1000 elements, but i had more than 10000 displayed in my windows forms application and had no issues with it.
The only difference with Windows Forms is that instead of using Binding i was setting the dataGridView's dataSource to the DataTable each time i was updating it.
Any ideas? What am i doing wrong?

Try setting EnableRowVirtualization=True

Related

How to duplicate a custom control (panel) programmatically

I am using C# in VS 2010. I created a custom panel and would like to add this custom panel 9 times so I created a loop to add a copy of the panel 9 times at equal distance from each other. Each panel will have its own text and image. All I'm getting though is a single panel. Any insight would be appreciated
public partial class Form1 : Form
{
int index = 0;
List<CutePanel.CustomPanel> MenuItems = new List<CutePanel.CustomPanel>();
public Form1()
{
InitializeComponent();
for (int i = 0; i < 9; i++)
{
this.cpTest.BackColor = System.Drawing.SystemColors.ActiveCaption;
this.cpTest.LabelText = "My super click text";
this.cpTest.Location = new System.Drawing.Point(12, 12+(64*i));
this.cpTest.Name = "cpTest";
this.cpTest.Size = new System.Drawing.Size(344, 58);
this.cpTest.SuperClick = null;
this.cpTest.TabIndex = 6;
}
cpTest.MouseClick += new MouseEventHandler(cpTest_MouseClick);
cpTest.SuperClick += new EventHandler(cpTest_SuperClick);
cpTest.LabelText = "This is my text.";
MenuItems.Add(cpTest);
}
void cpTest_SuperClick(object sender, EventArgs e)
{
tcTest.SelectedIndex = index++ % 2;
}
void cpTest_MouseClick(object sender, MouseEventArgs e)
{
tcTest.SelectedIndex = index++ % 2;
}
private void customPanel3_MouseClick(object sender, MouseEventArgs e)
{
tcTest.SelectedIndex = index++ % 2;
}
}
Thanks.
You have to make a distinction between your panel class and panel objects, also called instances of this class. Think of the class as a template that serves in creating objects. These objects are created with the new keyword:
for (int i = 0; i < 9; i++)
{
var cp = new CutePanel.CustomPanel();
cp.BackColor = System.Drawing.SystemColors.ActiveCaption;
cp.LabelText = "My super click text";
cp.Location = new System.Drawing.Point(12, 12+(64*i));
cp.Name = "cpTest" + i;
cp.Size = new System.Drawing.Size(344, 58);
cp.SuperClick = null;
cp.TabIndex = 6;
cp.MouseClick += new MouseEventHandler(cpTest_MouseClick);
cp.SuperClick += new EventHandler(cpTest_SuperClick);
cp.LabelText = "This is my text.";
MenuItems.Add(cp);
}
You can also assign it values from the existing panel:
cp.BackColor = cpTest.BackColor;
cp.Size = cpTest.Size;
...
An elegant way of making a duplicate is to include a Clone method in your panel class
public class CustomPanel
{
...
public CustomPanel Clone()
{
var cp = (CustomPanel)this.MemberwiseClone();
cp.Parent = null; // It has not yet been added to the form.
return cp;
}
}
Then
for (int i = 0; i < 9; i++)
{
CustomPanel cp = cpTest.Clone();
// Now only change the differing properties
cp.Location = new System.Drawing.Point(12, 12+(64*i));
cp.Name = "cpTest" + i;
cp.TabIndex += i + 1;
MenuItems.Add(cp);
}
but attention: If the cloned control is a container control containing other controls, you must clones those recursively as well. I.e., you must perform a deep clone! Creating new controls as shown in my first code snippet is safer.

remove items from combobox

i filled the combobox with the following:
for(var x in z)
{
var tempItem = new qx.ui.form.ListItem(""+arr[x]);
tempItem.model=arr[x];
cbo.add(tempItem);
}
Unfortunately, i didn't find anything, to remove all items from the combobox.
With the following code is this not possible
cbo.getList().removeAll();
or
var childLength = cbo.getList().getChildrenLength();
for (var i = 0; i < childLength; i ++)
{
var childToRemove = cbo.getList().getFirstChild();
cbo.getList().remove(childToRemove);
childToRemove.dispose();
childToRemove = null;
}
Thank you
Mani
Your snippet does not work because the cbo does not have any getList()-method. Performing removeAll() directly on the comboBox should do the trick.
Cheers
Andreas

How to add dynamically more line series into a line chart in wpf toolkit?

I'm trying to use wpf toolkit chart line and I need to have more then one line in the chart but i cant figer out how to do that I tried to look in here and Google but I always found an XAML code and I need to do it dynamically in c#. In the program I cant know how much charts i will need and how many line in every chart this is way I can't do it in the XAML...
for (int j = 0; j < 4; j++) //its just so i cant check it
{
ColumnDefinition cd = new ColumnDefinition();
myGrid.ColumnDefinitions.Add(cd);
Chart chart1 = new Chart();
LineSeries lineChart = new LineSeries();
chart1.Height = 200;
chart1.Width = 300;
chart1.Title = (j);
//((LineSeries)chart1.Series[0]).ItemsSource = valueList;
lineChart.DependentValuePath = "Value";
lineChart.IndependentValuePath = "Key";
lineChart.ItemsSource = valueList;
lineChart.IsSelectionEnabled = true;
chart1.Series.Add(lineChart);
lineChart.ItemsSource = valueList1;
chart1.Series.Add(lineChart); <---
myGrid.Children.Add(chart1);
Grid.SetColumn(chart1, (j));
Grid.SetRow(chart1, 0);
}
I tried this but it is not working ...
please help!:(
XAML:
<chartingToolkit:Chart Name="lineChart" />
Code-behind:
private void showChart(List<KeyValuePair<string, int>> valueList)
{
LineSeries lineSeries1 = new LineSeries();
lineSeries1.Title = "Title";
lineSeries1.DependentValuePath = "Value";
lineSeries1.IndependentValuePath = "Key";
lineSeries1.ItemsSource = valueList;
lineChart.Series.Add(lineSeries1);
}
Where you can define valueList as:
List<KeyValuePair<string, int>> valueList = new List<KeyValuePair<string, int>>();
and insert the desired values as valueList.Insert(0, new KeyValuePair<string, int>(key, value));

Silverlight Datagrid get cell value

I cant read cell text in datagrid. how can i do that? code and print screan on the image
thanks a lot
http://e1203.hizliresim.com/v/x/3x3dg.jpg code
http://e1203.hizliresim.com/v/x/3x3dw.jpg printscrean
here is the where i am creating grid; I think problem is ; I have two tables hr_Employee and hr_Scoring. when I bind "dayscore" from table hr_Scoring there is something wrong.
DomainServiceDB db = new DomainServiceDB();
//LoadOperation<hr_Employee> employeeLoadOp;
readonly Error err = new Error("Kaydederken hata oluştu. Lütfen tekrar deneyiniz.");
public PersonelUserControl()
{
InitializeComponent();
dgPersonelTakip.ItemsSource = db.hr_Employees;
db.Load(db.GetHr_EmployeeQuery());
int year = DateTime.Now.Year;
int month = DateTime.Now.Month;
int day = DateTime.DaysInMonth(year, month);
DataGridTextColumn adi = new DataGridTextColumn() { Header = "Adı ", Binding = new Binding("Name"), IsReadOnly = true };
DataGridTextColumn soyadi = new DataGridTextColumn() { Header = "Soyadı ", Binding = new Binding("Surname"), IsReadOnly = true };
dgPersonelTakip.Columns.Add(adi);
dgPersonelTakip.Columns.Add(soyadi);
for (int i = 1; i <= day; i++)
{
DataGridTextColumn c = new DataGridTextColumn()
{
IsReadOnly = false,
Header = i.ToString(),
// Binding = new Binding(path: "hr_Scorings.DayScore")
Binding = new Binding("hr_Scorings.DayScore")
};
dgPersonelTakip.Columns.Add(c);
}
}

How can I use WPF bindings while printing?

It seems not all bindings are to evaluated when printing. For example, in the code below, only the first button has content = "100", other buttons have content = "0".
var doc = new XpsDocument("test.xps",FileAccess.Write);
var writer = XpsDocument.CreateXpsDocumentWriter(doc);
var collator = writer.CreateVisualsCollator();
collator.BeginBatchWrite();
for (int i = 0; i < 3; i++)
{
var button = new Button();
button.SetBinding(ContentControl.ContentProperty,
new Binding
{
RelativeSource = new RelativeSource(RelativeSourceMode.Self),
Path = new PropertyPath("ActualWidth")
});
button.Measure(new Size(100, 100));
button.Arrange(new Rect(0, 0, 100, 100));
button.Width = 100;
button.Height = 100;
collator.Write(button);
}
collator.EndBatchWrite();
doc.Close();
Is there a workaround?
For example, is there a way to force the binding to evaluate?
Have you tried making sure the dispatcher is idle before the call to collator.EndBatchWrite().
Something like:
Dispatcher.CurrentDispatcher.Invoke(
new Action( delegate { } ), DispatcherPriority.ApplicationIdle, null );

Resources