Creating WPF examples in LinqPad - wpf

Is there any way to sanely instantiate WPF objects in LinqPad? Here's my example (the correct assemblies are added in the query, etc):
var w = new Window();
w.Loaded += (o,e) => {
w.Content = new TextBlock() { Text = "Foo" };
};
w.Show();
However, this dies a horrible death:
System.Runtime.InteropServices.InvalidComObjectException: COM object that has been separated from its underlying RCW cannot be used.
at System.Windows.Input.TextServicesContext.StopTransitoryExtension()
at System.Windows.Input.TextServicesContext.Uninitialize(Boolean appDomainShutdown)
at System.Windows.Input.TextServicesContext.TextServicesContextShutDownListener.OnShutDown(Object target, Object sender, EventArgs e)
at MS.Internal.ShutDownListener.HandleShutDown(Object sender, EventArgs e)
Any clues on how I can get this to work?

Another way to do it is as follows:
w.ShowDialog();
Dispatcher.CurrentDispatcher.InvokeShutdown(); // Cleanly end WPF session.
More examples:
new Window { Content = "Foo" }.ShowDialog();
new Window { Content = new Button { FontSize = 50, Content = "Foo" } }.ShowDialog();
Dispatcher.CurrentDispatcher.InvokeShutdown(); // Cleanly end WPF session.

You need to run a message loop by calling new Application().Run(w).

Related

How to display Object data in a TableLayoutPanel in a performant way

I have written the folowing code to populate the data from a object in a tablelayoutpanel control. It works Smile | :) , but when its loading the data onto the table, it flickers/jumps for few seconds and then after 2-3 seconds when its done processing the data it populates the data Frown | :( . I believe this behaviour is because of the code written for dynamically processing & drawing of the various controls in the table based on the object data.
I need your help in optimising the code/improving the performance of this code so that the table can load smoothly and fast. Please help. Thanks.
PS: This code is written for a table containing small amount of data. But going forward the same is planned for populating table with 4X more data. If this is the case, then performance will be very poor, which worries me. Please suggest some ideas.
private void button1_Click(object sender, EventArgs e)
{
Common obj = new Common();
obj.CreateDeserializedXmlObject(#"E:\TestReport.xml");
var v = obj.GetAdminData();
tableLayoutPanel1.ColumnCount = 4;
tableLayoutPanel1.RowCount = ((v.DOCREVISIONS.Length * 4) + 1 + (v.USEDLANGUAGES.L10.Length));
Label labelLanguage = new Label();
Label labelUsedLanguage = new Label();
Label labelDocRevisions = new Label();
labelLanguage.Text = "Language:";
labelUsedLanguage.Text = "Used Language:";
labelDocRevisions.Text = "Doc-Revisions:";
ComboBox comboBoxLanguage = new ComboBox();
comboBoxLanguage.Items.Add(v.LANGUAGE.Value.ToString());
comboBoxLanguage.SelectedIndex = 0;
ComboBox comboBoxUsedLanguage = new ComboBox();
foreach (LPLAINTEXT Lang in v.USEDLANGUAGES.L10)
{
comboBoxUsedLanguage.Items.Add(Lang.L.ToString());
}
comboBoxUsedLanguage.SelectedIndex = 0;
int index = 0;
Label[] labelDocRevision = new Label[v.DOCREVISIONS.Length];
Label[] labelRevision = new Label[v.DOCREVISIONS.Length];
Label[] labelState = new Label[v.DOCREVISIONS.Length];
Label[] labelTeamMember = new Label[v.DOCREVISIONS.Length];
Label[] labelDate = new Label[v.DOCREVISIONS.Length];
TextBox[] textBoxRevision = new TextBox[v.DOCREVISIONS.Length];
TextBox[] textBoxState = new TextBox[v.DOCREVISIONS.Length];
TextBox[] textBoxTeamMember = new TextBox[v.DOCREVISIONS.Length];
TextBox[] textBoxDate = new TextBox[v.DOCREVISIONS.Length];
foreach (DOCREVISION dcr in v.DOCREVISIONS)
{
labelDocRevision[index] = new Label();
labelRevision[index] = new Label();
labelState[index] = new Label();
labelTeamMember[index] = new Label();
labelDate[index] = new Label();
textBoxRevision[index] = new TextBox();
textBoxState[index] = new TextBox();
textBoxTeamMember[index] = new TextBox();
textBoxDate[index] = new TextBox();
labelDocRevision[index].Text = "DOCREVISION["+index.ToString()+"]:";
labelRevision[index].Text = "Revision:";
labelState[index].Text = "State:";
labelTeamMember[index].Text = "TeamMemberRef:";
labelDate[index].Text = "Date:";
textBoxRevision[index].Text = dcr.REVISIONLABEL.Value.ToString();
textBoxState[index].Text = dcr.STATE.Value.ToString();
textBoxTeamMember[index].Text = dcr.TEAMMEMBERREF.Value.ToString();
textBoxDate[index].Text = dcr.DATE.Value.ToString();
index++;
}
// Add child controls to TableLayoutPanel and specify rows and column
tableLayoutPanel1.Controls.Add(labelLanguage, 0, 0);
tableLayoutPanel1.Controls.Add(labelUsedLanguage, 0, 1);
tableLayoutPanel1.Controls.Add(labelDocRevisions, 0, 2);
tableLayoutPanel1.Controls.Add(comboBoxLanguage, 1, 0);
tableLayoutPanel1.Controls.Add(comboBoxUsedLanguage, 1, 1);
int docRevRowSpacing = 2;
for (int loop = 0; loop < index; loop++)
{
tableLayoutPanel1.Controls.Add(labelDocRevision[loop], 1, docRevRowSpacing);
tableLayoutPanel1.Controls.Add(labelRevision[loop], 2, docRevRowSpacing);
tableLayoutPanel1.Controls.Add(labelState[loop], 2, docRevRowSpacing+1);
tableLayoutPanel1.Controls.Add(labelTeamMember[loop], 2, docRevRowSpacing+2);
tableLayoutPanel1.Controls.Add(labelDate[loop], 2, docRevRowSpacing+3);
tableLayoutPanel1.Controls.Add(textBoxRevision[loop], 3, docRevRowSpacing);
tableLayoutPanel1.Controls.Add(textBoxState[loop], 3, docRevRowSpacing+1);
tableLayoutPanel1.Controls.Add(textBoxTeamMember[loop],3 , docRevRowSpacing+2);
tableLayoutPanel1.Controls.Add(textBoxDate[loop], 3, docRevRowSpacing+3);
docRevRowSpacing += 4;
}
tableLayoutPanel1.CellBorderStyle = TableLayoutPanelCellBorderStyle.Single;
Controls.Add(this.tableLayoutPanel1);
}
There are two minor changes that helps a little bit.
At the start of your code you can call SuspendLayout. This prevents the TableLayoutPanel to redraw itself every time you add a control to it. When you're done adding all controls at the end you call ResumeLayout. At that moment the TableLayoutPanel will redraw only once. It still takes time but at least most the flickering is gone. At the end of your example code you add the tableLayoutPanel1 again to the forms control collection. If the TableLayoutPanel is on your form designer you don't need that and by doing it you make your performance worse because now you have two tableLayoutPanels that need to be painted.
private void button1_Click(object sender, EventArgs e)
{
tableLayoutPanel1.SuspendLayout();
// all your other code goes here
// not sure why you add the tableLayouyPanel AGAIN to the
// form control collection.
// Controls.Add(this.tableLayoutPanel1);
tableLayoutPanel1.ResumeLayout();
}
I noticed in my testing that resizing the form gives the same flickering effect. I used the ResizeBegin and ResizeEnd events to do the same Suspend and Resume layout trick:
private void Form1_ResizeBegin(object sender, EventArgs e)
{
tableLayoutPanel1.SuspendLayout();
}
private void Form1_ResizeEnd(object sender, EventArgs e)
{
tableLayoutPanel1.ResumeLayout();
}
This as much as you can do with your current code (except maybe the use of all those arrays with controls but their overhead is not the major issue here).
The TableLayoutPanel is maybe not the best control for what you want to achieve. It lacks for example VirtualMode support, something the DataGridView does. That would enable you to only load and show data that is visible on the form (and therefor create controls for it). Adapting your code to use that control is left as an exercise for the reader and if new issues pop-up feel free to start a new question.

Exception Using Dynamically adding controls to silverlight childwindow?

I have a parameterised constructor in My Application. I want to add controls dynamically to my silverlight Child Control Page. But it gives NullReferenceException.
I can't find out why it returns null.Can any help me with this situation?
public PDFExport(FrameworkElement graphTile1, FrameworkElement graphTile2,FrameworkElement graphTile3)
{
Button btnGraph1 = new Button();
string Name = graphTile1.Name;
btnGraph1.Content = Name;
btnGraph1.Width = Name.Length;
btnGraph1.Height = 25;
btnGraph1.Click += new RoutedEventHandler(btnGraph1_Click);
objStack.Children.Add(btnGraph1);
LayoutRoot.Children.Add(objStack); // Here am getting null Reference Exception
_graphTile1 = graphTile1;
_graphTile2 = graphTile2;
_graphTile3 = graphTile3;
}
Thanks.
I guess objStack is a stackpanel declared in your XAML?
Be aware that the UI component of your xaml are build by the call to InitializeComponent.
Thus objStack will not exist until you call InitializeCOmponent() in your constructor.
Also, you should know that the call to InitializeComponent is asynchronous, so you code should look like something like that:
private readonly FrameworkElement _graphTile1;
private readonly FrameworkElement _graphTile2;
private readonly FrameworkElement _graphTile3;
public PDFExport(FrameworkElement graphTile1, FrameworkElement graphTile2, FrameworkElement graphTile3)
{
_graphTile1 = graphTile1;
_graphTile2 = graphTile2;
_graphTile3 = graphTile3;
}
private void PDFExport_OnLoaded(object sender, RoutedEventArgs e)
{
Button btnGraph1 = new Button();
string Name = _graphTile1.Name;
btnGraph1.Content = Name;
btnGraph1.Width = Name.Length;
btnGraph1.Height = 25;
btnGraph1.Click += new RoutedEventHandler(btnGraph1_Click);
objStack.Children.Add(btnGraph1);
LayoutRoot.Children.Add(objStack);
}
Hope it helps.
As per my research i got that, why it raises an exception: Because there is no
InitializeComponent() in My Constructor and am not calling parent constructor.
That is the reason it raises Exception.
Just Add InitializeComponent() to the code, simple

Show a RadDesktopAlert on form

i want to Show a RadDesktopAlert on a form (not on the desktop). therefore i use second constructor to set its container to form. but nullException raised for this.Container
am i in the correct line to show RadDesktopAlert on the form (it is better to say IN THE FORM)?
and why container is null?
here is my code
private void Form1_Load(object sender, EventArgs e)
{
Telerik.WinControls.UI.RadDesktopAlert q = new Telerik.WinControls.UI.RadDesktopAlert(this.Container);//null exception: Container is null
q.ScreenPosition = Telerik.WinControls.UI.AlertScreenPosition.BottomCenter;
q.ContentText = "what ever";
q.Show();
}
To do that you need to set the ScreenPosition to Manual and then set the popup location
Telerik.WinControls.UI.RadDesktopAlert q = new Telerik.WinControls.UI.RadDesktopAlert();//null exception: Container is null
q.ScreenPosition = Telerik.WinControls.UI.AlertScreenPosition.Manual;
q.Popup.Location = new Point(this.Location.X + 20, this.Location.Y + 20);
q.ContentText = "what ever";
q.Show();

visual studio (2010) combo box with more layers

I would like to ask you something about VS2010 combobox (CB) component...
Is it possible to make something like multilevel (categorised) CB? I mean, can I divide items in CB into categories or somthing like this?
There is similar component in html (tag optgroup) - it's exactly what I need:
multilevel combobox in html
Thanx very much for answer
P.S.: Sorry for my english, I hope I've described it clearly
If you change the DrawMode of the ComboBox to OwnerDrawFixed and you can use the DrawItem event to draw your header and your items. But there is nothing you can do to prevent the user from selecting a header item.
private List<string> groupItems = new List<string>();
private void Form1_Load(object sender, EventArgs e)
{
groupItems.Add("Great Bands");
groupItems.Add("Great Bandages");
comboBox1.DrawMode = DrawMode.OwnerDrawFixed;
comboBox1.Items.Add("Great Bands");
comboBox1.Items.Add("Led Zeppelin");
comboBox1.Items.Add("Steppenwolf");
comboBox1.Items.Add("Great Bandages");
comboBox1.Items.Add("Band-Aid");
comboBox1.Items.Add("Curad");
}
private void comboBox1_DrawItem(object sender, DrawItemEventArgs e)
{
e.DrawBackground();
if (e.Index > -1)
{
string drawText = comboBox1.Items[e.Index].ToString();
if (groupItems.Contains(drawText))
{
using (Font font = new Font(comboBox1.Font, FontStyle.Bold))
e.Graphics.DrawString(drawText, font, Brushes.Black, e.Bounds);
}
else
e.Graphics.DrawString(drawText, comboBox1.Font, Brushes.Black, new Rectangle(16, e.Bounds.Top, e.Bounds.Width - 16, e.Bounds.Height));
e.DrawFocusRectangle();
}
}

How to display Bitmap Image in image control on WPF using C#

I want that when I double click on a row in ListView, it should display the Image corresponding to that row. This row also contains the path of the Image.
I tried the following but it displays the same Image for all rows because I have given the path for a specific Image:
private void ListViewEmployeeDetails_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
ImageSource imageSource = new BitmapImage(new Uri(#"C:\northwindimages\king.bmp"));
image1.Source = imageSource;
}
Please suggest something.
They key is to retrieve the row index that was clicked, and get the image URL for that row. Since you say you are clicking on the row, this can be done in a method similar to that below
private void ListViewEmployeeDetails_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
DataRow row = (DataRow)sender; //Get the row that was clicked
string imageURL = row["imageUrl"].ToString();//Get the img URL for that row
ImageSource imageSource = new BitmapImage(new Uri(imageURL));
image1.Source = imageSource;
}
Hope this helps
Suppose that:
The list you are binding to contains Elephant objects and,
You want the image to show Elephant.Picture whenever you double-click an item.
You can set the image from an event handler as follows:
private void ListViewEmployeeDetails_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
var viewItem = sender as ListViewItem;
if(viewItem!=null)
{
var elephant = viewItem.DataContext as Elephant;
image1.Source = elephant.Picture;
}
}
Note that it is important to only accept double clicks on the ListViewItem.
The above code assumes that elephant.Picture is of type ImageSource. If it is something else you will have to convert it. For example, if instead Elephant has a string "PicturePath" property, the image1.Source line would change to:
image1.Source = new BitmapImage(new Uri(elephant.PicturePath));

Resources