I have a WPF Application which allows user to enter production Data.
For that reason i created a Usercontrol which uses an WPF Toolkit Accordion. In Code behind i create 15 Accordion Items. Each Item has an Stackpanel and 5-10 Textboxes in it.
When adding 12 of these controls to the main Content Control it takes about 10 seconds.
What can be the cause of this behaviour?
public XXXMeasurementControl(Measurement meas)
{
InitializeComponent();
if (meas.ID == -2)
{
LineNameTextBlock.Text = "Total";
}
else
{
LineNameTextBlock.Text = meas.MeasureDate.ToString("HH:mm") + " - " + meas.MeasureDate.AddHours(1).ToString("HH:mm");
}
this.cells = meas.MainCells;
this.meas = meas;
Binding b = new Binding();
Remark.DataContext = Meas;
b.Mode = BindingMode.TwoWay;
b.Path = new PropertyPath("Remark");
BindingOperations.SetBinding(Remark, TextBox.TextProperty, b);
//Create Cells Start
foreach (Cell c in cells)
{
//Creating Textboxes & Bindings for Stations from Maincells
if (c.Name != "OQC")
{
//Setting Qualified Overall (=Qualified from Cell Appearance Check)
Common.BindTextBlock(QualifiedOverallTextBlock, c, "Qualified");
if (c.Name.Contains("Appearance Check"))
Common.BindTextBlock(QualifiedOverallTextBlock, c, "Qualified");
//Setting Scrap Rate (=Waste from Cell Acoustic Test)
if (c.Name.Contains("Acoustic Test"))
Common.BindTextBlock(ScrapRateTextBlock, c, "WasteRate");
AccordionItem aci = new AccordionItem();
StackPanel sp = new StackPanel();
StackPanel groupData = new StackPanel();
StackPanel all = new StackPanel();
all.Children.Add(sp);
all.Children.Add(groupData);
if (c.Stations != null)
//All Single Cell Line Controls
if (meas.ID != -2)
{
for (int i = 0; i < c.Stations.Count; i++)
{
NumberTextbox t = Common.CreateNumberTextbox(c.Stations[i], "Value", BindingMode.TwoWay, false, null, 80, 22);
t.LostFocus += new RoutedEventHandler(t_LostFocus);
c.Stations[i].PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(LineControl_PropertyChanged);
//Handling if Qualified Field is Editable
if (c.Stations[i].Name.Contains("Qualified"))
{
t.Background = new SolidColorBrush(Colors.BlanchedAlmond);
groupData.Children.Add(t);
}
else
{
sp.Children.Add(t);
}
}
}
groupData.Children.Add(Common.CreateNumberTextbox(c, "RejectQty", BindingMode.OneWay, true,null, 80, 22));
groupData.Children.Add(Common.CreateNumberTextbox(c, "PassRate", BindingMode.OneWay, true, new SolidColorBrush(Colors.BlanchedAlmond), 80, 22));
groupData.Children.Add(Common.CreateNumberTextbox(c, "RejectRate", BindingMode.OneWay, true, new SolidColorBrush(Colors.BlanchedAlmond), 80, 22));
aci.Header = "";
aci.Content = all;
MainCellsAccordion.Items.Add(aci);
}
}
}
I too experience terrible performance with the Accordion control in the WPF Toolkit. I have an Accordion control within a tab, and whenever I switch to that tab it takes a solid 2-3 seconds to initialize the contents. I do not have this problem when the Accordion Control is not being used.
I think the Accordion is your culprit.
Related
In the Form constructor I generate an array of panels (pnl_ in the code below), that include radiobuttons.
When I visualize the Form, only panels are visible, NOT radiobuttons inside.
Curiously, everything is OK, when I generate only one panel (pnl in the code below).
public partial class Radiobuttons_on_Panel : Form
{
private Panel pnl = new Panel();
private RadioButton rbtn1 = new RadioButton();
private RadioButton rbtn2 = new RadioButton();
private Panel[] pnl_ = new Panel[7];
private RadioButton[] rbtn1_ = new RadioButton[7];
private RadioButton[] rbtn2_ = new RadioButton[7];
public Radiobuttons_on_Panel()
{
InitializeComponent();
pnl.Location = new Point(10, 10);
pnl.Size = new Size(100, 100);
pnl.BorderStyle = BorderStyle.FixedSingle;
rbtn1.Location = pnl.Location;
rbtn1.Text = "AAA";
rbtn2.Location = new Point(pnl.Location.X, pnl.Location.Y + rbtn1.Height);
rbtn2.Text = "BBB";
pnl.Controls.Add(rbtn1);
pnl.Controls.Add(rbtn2);
this.Controls.Add(pnl);
for (int i = 0; i < pnl_.Length; i++)
{
pnl_[i] = new Panel();
pnl_[i].BorderStyle = BorderStyle.FixedSingle;
pnl_[i].Size = new Size(100, 100);
pnl_[i].Location = new Point(10 + i * 110, 200);
rbtn1_[i] = new RadioButton();
rbtn1_[i].Location = pnl_[i].Location;
rbtn1_[i].Text = "AAA";
rbtn2_[i] = new RadioButton();
rbtn2_[i].Location = new Point(pnl_[i].Location.X, pnl_[i].Location.Y + rbtn1_[i].Height);
rbtn2_[i].Text = "BBB";
pnl_[i].Controls.Add(rbtn1_[i]);
pnl_[i].Controls.Add(rbtn2_[i]);
this.Controls.Add(pnl_[i]);
}
}
}
Where is the problem?
Your problem with this is that your calculation of location is wrong. The location of the radio buttons are relative to their container - in this case, the panels. If you just set your locations to
rbtn1_[i] = new RadioButton();
rbtn1_[i].Location = new Point(10, 10);
rbtn1_[i].Text = "AAA";
rbtn2_[i] = new RadioButton();
rbtn2_[i].Location = new Point(rbtn1_[i].Location.X, rbtn1_[i].Location.Y + rbtn1_[i].Height);
rbtn2_[i].Text = "BBB";
the buttons will lay out like you want them to.
Thing work out in your first one because your radio button locations values are small enough to be visible in the panel. For those others, well, they are outside the bounds of their parent panels.
The long and short of it is that the Location property is always relative to the container, whether that is a Panel or a Form - the Location values for your panels are relative to the Form but the the Location values for your radio buttons are relative to whatever panel they are in.
MSDN Reference: http://msdn.microsoft.com/en-us/library/system.windows.forms.control.location.aspx
I added a Line with C# code to my canvas, along with a context menu and attached event. I would like to rotate the Line using a context menu choice, not the menu text in the context menu:
newMenuItem1.PreviewMouseDown += new MouseButtonEventHandler((sx, ex) => {
MenuItem menuItem = (MenuItem)sx;
string theHeader = menuItem.Header.ToString();
if (theHeader.Contains("90")) {
Line ow = ex.Source as Line;
rt = new RotateTransform(90, 25, 50);
ow.RenderTransform = rt;
}
});
This code produces a null reference exception. If I substitute:
UIElement ow = ex.Source as UIElement;
The actual menu text will rotate!
Edit:
Here is more code, I am now trying originalsource too:
private void button1_Click(object sender, RoutedEventArgs e)
{
Line g = new Line();
g.Stroke = System.Windows.Media.Brushes.LawnGreen;
g.X1 = 0; g.X2 = 100;g.Y1 = 0;g.Y2 = 0;
g.HorizontalAlignment = HorizontalAlignment.Left;
g.VerticalAlignment = VerticalAlignment.Center;
g.StrokeThickness = 6;
ContextMenu k = new ContextMenu();
g.ContextMenu = k;
MenuItem newMenuItem1 = new MenuItem();
MenuItem newMenuItem2 = new MenuItem();
MenuItem newMenuItem3 = new MenuItem();
newMenuItem1.Header = "Rotate 90";
newMenuItem2.Header = "Rotate 180";
newMenuItem3.Header = "Rotate 270";
newMenuItem1.PreviewMouseDown += new MouseButtonEventHandler((sx, ex) => {
MenuItem menuItem = (MenuItem)sx;
string theHeader = menuItem.Header.ToString();
if (theHeader.Contains("90")) {
Line ow = (Line)ex.OriginalSource;
rt = new RotateTransform(90, 25, 50);
ow.RenderTransform = rt;
}
});
g.ContextMenu.Items.Add(newMenuItem1);
g.ContextMenu.Items.Add(newMenuItem2);
g.ContextMenu.Items.Add(newMenuItem3);
Canvas.SetTop(g, 18);
Canvas.SetLeft(g, 18);
MyCanvas.Children.Add(g);
///////
I also tried:
private static T FindAncestor<T>(DependencyObject current)
where T : DependencyObject
{
do
{
if (current is T)
{
return (T)current;
}
current = VisualTreeHelper.GetParent(current);
}
while (current != null);
return null;
}
but it does not work. My next plan is to get coordinates off the canvas, and try to determine what control sits there. This will become tricky though if an object is transformed, because I believe the UI sees it at the original position. I've experimented with other controls as well, like the TextBox and get similar issues.
A really quick and dirty way to do this would be to add your line to the menu item's tag property and retrieve it in the PreviewMouseDown handler
When creating your context menu:
newMenuItem1.Tag = g;
In you handler:
Line ow = ((FrameworkElement)ex.Source).Tag as Line;
The less quick and dirty way to do this would be to use the ContextMenuOpening event on your line as that should be sent with the sender equal to the control itself. You could then store a reference to the line somewhere and retrieve it again in the menu item click event. This works better when you have multiple lines (which I'm guess is what you intend) and just one context menu (instead of producing a bunch of copies of the same menu as you are doing now).
i want to print a grid which is generated dynamically.
Means, in the click event of the Print Button, i m generating a grid and then i want to print that grid.
here is my code,
private void btnPrint_Click(object sender, RoutedEventArgs e)
{
PrintDialog Objprint = new System.Windows.Controls.PrintDialog();
if (Objprint.ShowDialog() == true)
{
System.Printing.PrintCapabilities capabilities = Objprint.PrintQueue.GetPrintCapabilities(Objprint.PrintTicket);
double scale = Math.Min(capabilities.PageImageableArea.ExtentWidth / this.ActualWidth, capabilities.PageImageableArea.ExtentHeight / this.ActualHeight);
#region "Make a grid For Printing"
Grid objgrid = new Grid();
objgrid.Name = "GridForPrinting";
objgrid.Width = 1000;
objgrid.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
objgrid.VerticalAlignment = System.Windows.VerticalAlignment.Top;
objgrid.RowDefinitions.Add(new RowDefinition());
TextBlock objtext = new TextBlock();
objtext.HorizontalAlignment = System.Windows.HorizontalAlignment.Center;
objtext.VerticalAlignment = System.Windows.VerticalAlignment.Center;
objtext.Text = "SUPERIOR COURT OF CALIF COUNTY OF SAN BERNARDINO";
Grid.SetRow(objtext, 0);
objgrid.Children.Add(objtext);
#endregion
Objprint.PrintVisual(objgrid, "Case Summary");
}
}
this code give me blank page to print.
how can i do that?
here i get answer,
from the below code i get what i want to do...
void PrintOnClick(object sender, RoutedEventArgs args)
{
PrintDialog dlg = new PrintDialog();
if ((bool)dlg.ShowDialog().GetValueOrDefault())
{
// Create Grid panel.
Grid grid = new Grid();
// Define 5 auto-sized rows and columns.
for (int i = 0; i < 5; i++)
{
ColumnDefinition coldef = new ColumnDefinition();
coldef.Width = GridLength.Auto;
grid.ColumnDefinitions.Add(coldef);
RowDefinition rowdef = new RowDefinition();
rowdef.Height = GridLength.Auto;
grid.RowDefinitions.Add(rowdef);
}
// Give the Grid a gradient brush.
grid.Background =
new LinearGradientBrush(Colors.Black, Colors.White,
new Point(0, 0), new Point(1, 1));
// Every program needs some randomness.
Random rand = new Random();
// Fill the Grid with 25 buttons.
for (int i = 0; i < 25; i++)
{
Button btn = new Button();
btn.FontSize = 12 + rand.Next(8);
btn.Content = "Button No. " + (i + 1);
btn.HorizontalAlignment = HorizontalAlignment.Center;
btn.VerticalAlignment = VerticalAlignment.Center;
btn.Margin = new Thickness(6);
grid.Children.Add(btn);
Grid.SetRow(btn, i % 5);
Grid.SetColumn(btn, i / 5);
}
// Size the Grid.
grid.Measure(new Size(Double.PositiveInfinity,
Double.PositiveInfinity));
Size sizeGrid = grid.DesiredSize;
// Determine point for centering Grid on page.
Point ptGrid =
new Point((dlg.PrintableAreaWidth - sizeGrid.Width) / 2,
(dlg.PrintableAreaHeight - sizeGrid.Height) / 2);
// Layout pass.
grid.Arrange(new Rect(ptGrid, sizeGrid));
// Now print it.
dlg.PrintVisual(grid, Title);
}
}
The PrintVisual print a Visual object. That means, by using the PrintVisual method, we can print any control, container, Window or user control that is in the visualtree.You cannot print a control that is not in the visualtree
I worked out the C# code to create an ImageButton (below) that has three images (one base-image and two overlays) and three text boxes as the face of the button. I am inheriting from the Button class, which unfortunately includes several components that I didn't realize would surface until after coding and need to remove, namely the bright-blue surrounding border on IsMouseOver, and any visible borders between the buttons, as the buttons will end up in a wrapPanel and the borders need to be seamless. Now that the format has been worked out in C#, I expect that I need to translate to XAML so that I can create a ControlTemplate to get the functionality necessary, however I am not certain as to the process of translating from C# to XAML. I would appreciate if anyone is aware of a good overview/resource that discusses what will be required to convert so that I can translate appropriately? Thanks.
public class ACover : Button
{
Image cAImage = null;
Image jCImage = null;
Image jCImageOverlay = null;
TextBlock ATextBlock = null;
TextBlock AbTextBlock = null;
TextBlock RDTextBlock = null;
private string _TracksXML = "";
public ACover()
{
Grid cArtGrid = new Grid();
cArtGrid.Background = new SolidColorBrush(Color.FromRgb(38, 44, 64));
cArtGrid.Margin = new System.Windows.Thickness(5, 10, 5, 10);
RowDefinition row1 = new RowDefinition();
row1.Height = new GridLength(225);
RowDefinition row2 = new RowDefinition();
row2.Height = new GridLength(0, GridUnitType.Auto);
RowDefinition row3 = new RowDefinition();
row3.Height = new GridLength(0, GridUnitType.Auto);
RowDefinition row4 = new RowDefinition();
row4.Height = new GridLength(0, GridUnitType.Auto);
cArtGrid.RowDefinitions.Add(row1);
cArtGrid.RowDefinitions.Add(row2);
cArtGrid.RowDefinitions.Add(row3);
cArtGrid.RowDefinitions.Add(row4);
ColumnDefinition col1 = new ColumnDefinition();
col1.Width = new GridLength(0, GridUnitType.Auto);
cArtGrid.ColumnDefinitions.Add(col1);
jCImage = new Image();
jCImage.Height = 240;
jCImage.Width = 260;
jCImage.VerticalAlignment = VerticalAlignment.Top;
jCImage.Source = new BitmapImage(new Uri(Properties.Settings.Default.pathToGridImages + "jc.png", UriKind.Absolute));
cArtGrid.Children.Add(jCImage);
cArtImage = new Image();
cArtImage.Height = 192;
cArtImage.Width = 192;
cArtImage.Margin = new System.Windows.Thickness(3, 7, 0, 0);
cArtImage.VerticalAlignment = VerticalAlignment.Top;
cArtGrid.Children.Add(cArtImage);
jCImageOverlay = new Image();
jCImageOverlay.Height = 192;
jCImageOverlay.Width = 192;
jCImageOverlay.Margin = new System.Windows.Thickness(3, 7, 0, 0);
jCImageOverlay.VerticalAlignment = VerticalAlignment.Top;
jCImageOverlay.Source = new BitmapImage(new Uri( Properties.Settings.Default.pathToGridImages + "jc-overlay.png", UriKind.Absolute));
cArtGrid.Children.Add(jCImageOverlay);
ATextBlock = new TextBlock();
ATextBlock.Foreground = new SolidColorBrush(Color.FromRgb(173, 176, 198));
ATextBlock.Margin = new Thickness(10, -10, 0, 0);
cArtGrid.Children.Add(ATextBlock);
AlTextBlock = new TextBlock();
AlTextBlock.Margin = new Thickness(10, 0, 0, 0);
AlTextBlock.Foreground = new SolidColorBrush(Color.FromRgb(173, 176, 198));
cArtGrid.Children.Add(AlTextBlock);
RDTextBlock = new TextBlock();
RDTextBlock.Margin = new Thickness(10, 0, 0, 0);
RDTextBlock.Foreground = new SolidColorBrush(Color.FromRgb(173, 176, 198));
cArtGrid.Children.Add(RDTextBlock);
Grid.SetColumn(jCImage, 0);
Grid.SetRow(jCImage, 0);
Grid.SetColumn(jCImageOverlay, 0);
Grid.SetRow(jCImageOverlay, 0);
Grid.SetColumn(cArtImage, 0);
Grid.SetRow(cArtImage, 0);
Grid.SetColumn(ATextBlock, 0);
Grid.SetRow(ATextBlock, 1);
Grid.SetColumn(AlTextBlock, 0);
Grid.SetRow(AlTextBlock, 2);
Grid.SetColumn(RDTextBlock, 0);
Grid.SetRow(RDTextBlock, 3);
this.Content = cArtGrid;
}
public string A
{
get { if (ATextBlock != null) return ATextBlock.Text;
else return String.Empty; }
set { if (ATextBlock != null) ATextBlock.Text = value; }
}
public string Al
{
get { if (AlTextBlock != null) return AlTextBlock.Text;
else return String.Empty; }
set { if (AlTextBlock != null) AlTextBlock.Text = value; }
}
public string RD
{
get { if (RDTextBlock != null) return RDTextBlock.Text;
else return String.Empty; }
set { if (RDTextBlock != null) RDTextBlock.Text = value; }
}
public ImageSource Image
{
get { if (cArtImage != null) return cArtImage.Source;
else return null; }
set { if (cArtImage != null) cArtImage.Source = value; }
}
public string TracksXML
{
get { return _TracksXML; }
set { _TracksXML = value; }
}
public double ImageWidth
{
get { if (cArtImage != null) return cArtImage.Width;
else return double.NaN; }
set { if (cArtImage != null) cArtImage.Width = value; }
}
public double ImageHeight
{
get { if (cArtImage != null) return cArtImage.Height;
else return double.NaN; }
set { if (cArtImage != null) cArtImage.Height = value; }
}
}
XAML basically represents an object graph, so the translation should normally be pretty mechanical:
C# new translates to a XAML element tag, e.g. Grid cArtGrid = new Grid(); translates to <Grid Name="cArtGrid"></Grid>.
C# property setters translate to attributes if the value is simple, e.g. cArtGrid.Background = new SolidColorBrush(Color.FromRgb(38, 44, 64)); translates to <Grid Background="#FF262C40">.
If the property value is complex, you'll need to use XAML property element syntax.
Adding to collections typically requires XAML property element syntax, e.g. <Grid><Grid.RowDefinitions><RowDefinition Height="225" /></Grid.RowDefinitions></Grid>.
But for the Children collection you can just put the element directly inside e.g. cArtGrid.Children.Add(jCImage); becomes <Grid><Image ... /></Grid>. (The same applies to the Content property though this won't really affect you here.)
Attached property SetXxx calls translate into attributes with the dot notation e.g. Grid.SetColumn(ATextBlock, 0); becomes <Grid><TextBlock Grid.Column="0" /></Grid>.
You'll need to understand how value types like colours and thicknesses are represented e.g. the #AARRGGBB notation for colours and the CSV notation for thicknesses. MSDN will usually show this for the relevant types or properties that have those types.
In general, looking up the property in MSDN and looking at the XAML syntax should give you a good start.
It sounds like you're attempting to extend the button with some new functionality. So the first thing you want to do is take advantage of the dependency system so that your properties can be bound in XAML. Look at this article on MSDN for information on declaring new dependency properties.
A prime candidate for a dependency property would be the Image property.
Actually, what I recommend is using the new CustomControl template in visual studio to provide some boilerplate code for you. Part of the boilerplate is declaring a themes.xaml file which provides a default template for your control. That template is what will hold your translated XAML for your control.
The good thing about XAML is that it is an initialization language. Once you get the dependency properties declared on your AlbumCover you bind to them in the template for your control. For more details about how this works, look at Charles Petzold's article on creating lookless controls in WPF.
You've got the basic look and functionality for your control in place. Following these two resources should help you integrate within the WPF ecosystem.
It seems like a simple question but how do I set the bacground color of the 'tab control', it seems to be derived from the standard window theme color. Is it Possible to create a black tab control with white text written on the tabs themselves (not the tab page)?
Help, I,m a little familiar with custom controls extending existing controls but I don't know what properties (if they exist) to set.
http://dotnetrix.co.uk/tabcontrol.htm
private void tabControl1_DrawItem(object sender, System.Windows.Forms.DrawItemEventArgs e)
{
TabPage CurrentTab = tabControl1.TabPages[e.Index];
Rectangle ItemRect = tabControl1.GetTabRect(e.Index);
SolidBrush FillBrush = new SolidBrush(Color.Red);
SolidBrush TextBrush = new SolidBrush(Color.White);
StringFormat sf = new StringFormat();
sf.Alignment = StringAlignment.Center;
sf.LineAlignment = StringAlignment.Center;
//If we are currently painting the Selected TabItem we'll
//change the brush colors and inflate the rectangle.
if (System.Convert.ToBoolean(e.State & DrawItemState.Selected))
{
FillBrush.Color = Color.White;
TextBrush.Color = Color.Red;
ItemRect.Inflate(2, 2);
}
//Set up rotation for left and right aligned tabs
if (tabControl1.Alignment == TabAlignment.Left || tabControl1.Alignment == TabAlignment.Right)
{
float RotateAngle = 90;
if (tabControl1.Alignment == TabAlignment.Left)
RotateAngle = 270;
PointF cp = new PointF(ItemRect.Left + (ItemRect.Width / 2), ItemRect.Top + (ItemRect.Height / 2));
e.Graphics.TranslateTransform(cp.X, cp.Y);
e.Graphics.RotateTransform(RotateAngle);
ItemRect = new Rectangle(-(ItemRect.Height / 2), -(ItemRect.Width / 2), ItemRect.Height, ItemRect.Width);
}
//Next we'll paint the TabItem with our Fill Brush
e.Graphics.FillRectangle(FillBrush, ItemRect);
//Now draw the text.
e.Graphics.DrawString(CurrentTab.Text, e.Font, TextBrush, (RectangleF)ItemRect, sf);
//Reset any Graphics rotation
e.Graphics.ResetTransform();
//Finally, we should Dispose of our brushes.
FillBrush.Dispose();
TextBrush.Dispose();
}
I use something like this in mu TabControl derived class (and it will do gradients too):
protected override void OnDrawItem(DrawItemEventArgs e)
{
// fill in the whole rect
using (SolidBrush br = new SolidBrush(Theme.FormBackColor))
{
e.Graphics.FillRectangle(br, ClientRectangle);
}
// draw the tabs
for (int i = 0; i < TabPages.Count; ++i)
{
TabPage tab = TabPages[i];
// Get the text area of the current tab
RectangleF tabTextArea = (RectangleF)GetTabRect(i);
// determine how to draw the tab based on which type of tab it is
Color tabTopBackColor = GetTopBackColor();
Color tabBottomBackColor = GetBottomBackColor();
Color tabTextColor = GetTextColor();
// draw the background
using (LinearGradientBrush br = new LinearGradientBrush(tabTextArea, tabTopBackColor, tabBottomBackColor, LinearGradientMode.Vertical))
{
e.Graphics.FillRectangle(br, tabTextArea);
}
// draw the tab header text
using (SolidBrush brush = new SolidBrush(tabTextColor))
{
e.Graphics.DrawString(tab.Text, Font, brush, CreateTabHeaderTextRect(tabTextArea));
}
}
}
private RectangleF CreateTabHeaderTextRect(RectangleF tabTextArea)
{
tabTextArea.X += 3;
tabTextArea.Y += 1;
tabTextArea.Height -= 1;
return tabTextArea;
}