Panels in UserControl - enable design support - winforms

I've build very simple user control that has TableLayoutPanel in it.
I've created layout as so
My idea is to have control that will become layout (template) for all other controls and forms.
Middle column is fixed, but first and third column can be fixed or autosized.
What I need now is to add Design Time Support to allow user to add controls only to those 4 panels.
I've tried adding:
[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))]
but this way I can only move controls around, they aren't added to my panels.
My code so far:
[Designer("System.Windows.Forms.Design.ParentControlDesigner, System.Design", typeof(IDesigner))]
public partial class CustomGrid : UserControl
{
public CustomGrid()
{
InitializeComponent();
}
private bool _firstFixed = true;
[Browsable(true)]
[Category("Grid")]
public bool FirstFixed
{
get { return _firstFixed; }
set { _firstFixed = value; ReLayout();}
}
private float _firstSize = 200F;
[Browsable(true)]
[Category("Grid")]
public float FirstSize
{
get { return _firstSize; }
set { _firstSize = value; ReLayout(); }
}
private float _secondSize = 200F;
[Browsable(true)]
[Category("Grid")]
public float SecondSize
{
get { return _secondSize; }
set { _secondSize = value; ReLayout(); }
}
private bool _thirdFixed = true;
[Browsable(true)]
[Category("Grid")]
public bool ThirdFixed
{
get { return _thirdFixed; }
set { _thirdFixed = value; ReLayout(); }
}
private float _thirdSize = 200F;
[Browsable(true)]
[Category("Grid")]
public float ThirdSize
{
get { return _thirdSize; }
set { _thirdSize = value; ReLayout(); }
}
private void ReLayout()
{
grid.ColumnStyles.Clear();
grid.ColumnStyles.Add(_firstFixed ? new ColumnStyle(SizeType.Absolute, _firstSize) : new ColumnStyle(SizeType.Percent, 33.33F));
grid.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, _secondSize));
grid.ColumnStyles.Add(_thirdFixed ? new ColumnStyle(SizeType.Absolute, _thirdSize) : new ColumnStyle(SizeType.Percent, 33.33F));
}
}
Designer code:
partial class CustomGrid
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.grid = new System.Windows.Forms.TableLayoutPanel();
this.panel1 = new System.Windows.Forms.Panel();
this.panel2 = new System.Windows.Forms.Panel();
this.panel3 = new System.Windows.Forms.Panel();
this.panel4 = new System.Windows.Forms.Panel();
this.grid.SuspendLayout();
this.SuspendLayout();
//
// grid
//
this.grid.BackColor = System.Drawing.Color.White;
this.grid.ColumnCount = 3;
this.grid.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 200F));
this.grid.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 200F));
this.grid.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.grid.Controls.Add(this.panel1, 0, 0);
this.grid.Controls.Add(this.panel2, 1, 0);
this.grid.Controls.Add(this.panel3, 2, 0);
this.grid.Controls.Add(this.panel4, 1, 1);
this.grid.Dock = System.Windows.Forms.DockStyle.Fill;
this.grid.Location = new System.Drawing.Point(0, 0);
this.grid.Margin = new System.Windows.Forms.Padding(0);
this.grid.Name = "grid";
this.grid.RowCount = 2;
this.grid.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 100F));
this.grid.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.grid.Size = new System.Drawing.Size(774, 430);
this.grid.TabIndex = 0;
//
// panel1
//
this.panel1.BackColor = System.Drawing.Color.White;
this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel1.Location = new System.Drawing.Point(5, 5);
this.panel1.Margin = new System.Windows.Forms.Padding(5);
this.panel1.Name = "panel1";
this.grid.SetRowSpan(this.panel1, 2);
this.panel1.Size = new System.Drawing.Size(190, 420);
this.panel1.TabIndex = 0;
//
// panel2
//
this.panel2.BackColor = System.Drawing.Color.White;
this.panel2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.panel2.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel2.Location = new System.Drawing.Point(205, 5);
this.panel2.Margin = new System.Windows.Forms.Padding(5);
this.panel2.Name = "panel2";
this.panel2.Size = new System.Drawing.Size(190, 90);
this.panel2.TabIndex = 1;
//
// panel3
//
this.panel3.BackColor = System.Drawing.Color.White;
this.panel3.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.panel3.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel3.Location = new System.Drawing.Point(405, 5);
this.panel3.Margin = new System.Windows.Forms.Padding(5);
this.panel3.Name = "panel3";
this.grid.SetRowSpan(this.panel3, 2);
this.panel3.Size = new System.Drawing.Size(364, 420);
this.panel3.TabIndex = 2;
//
// panel4
//
this.panel4.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
this.panel4.Dock = System.Windows.Forms.DockStyle.Fill;
this.panel4.Location = new System.Drawing.Point(205, 105);
this.panel4.Margin = new System.Windows.Forms.Padding(5);
this.panel4.Name = "panel4";
this.panel4.Size = new System.Drawing.Size(190, 320);
this.panel4.TabIndex = 3;
//
// CustomGrid
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.grid);
this.Margin = new System.Windows.Forms.Padding(0);
this.Name = "CustomGrid";
this.Size = new System.Drawing.Size(774, 430);
this.grid.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.TableLayoutPanel grid;
private System.Windows.Forms.Panel panel1;
private System.Windows.Forms.Panel panel2;
private System.Windows.Forms.Panel panel3;
private System.Windows.Forms.Panel panel4;
}
I've tried adding custom ControlDesigner (How do I provide designer support to a TabControl residing in a UserControl, so that I can drag/drop controls onto tab pages?) but without any luck.
My designer:
internal class CustomGridControlDesigner : ParentControlDesigner
{
public override void Initialize(IComponent component)
{
base.Initialize(component);
var ctl = Control as CustomGrid;
foreach (object ctrl in ctl.Controls)
{
if (ctrl.GetType() != typeof (Panel)) continue;
var ctrl1 = ctrl as Panel;
EnableDesignMode(ctrl1, ctrl1.Name);
}
}
}
My question is how can I add support for dragging and dropping controls to panels that are inside my control?
EDIT:
I've changed my code:
[Designer(typeof(CustomGridControlDesigner))]
public partial class CustomGrid : UserControl
{
public CustomGrid()
{
InitializeComponent();
}
private bool _firstFixed = true;
[Browsable(true)]
[Category("Grid")]
public bool FirstFixed
{
get { return _firstFixed; }
set { _firstFixed = value; ReLayout();}
}
private float _firstSize = 200F;
[Browsable(true)]
[Category("Grid")]
public float FirstSize
{
get { return _firstSize; }
set { _firstSize = value; ReLayout(); }
}
private float _secondSize = 200F;
[Browsable(true)]
[Category("Grid")]
public float SecondSize
{
get { return _secondSize; }
set { _secondSize = value; ReLayout(); }
}
private bool _thirdFixed = true;
[Browsable(true)]
[Category("Grid")]
public bool ThirdFixed
{
get { return _thirdFixed; }
set { _thirdFixed = value; ReLayout(); }
}
private float _thirdSize = 200F;
[Browsable(true)]
[Category("Grid")]
public float ThirdSize
{
get { return _thirdSize; }
set { _thirdSize = value; ReLayout(); }
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public Panel Panel1
{
get { return this.panel1; }
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public Panel Panel2
{
get { return this.panel2; }
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public Panel Panel3
{
get { return this.panel3; }
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]
public Panel Panel4
{
get { return this.panel4; }
}
private void ReLayout()
{
grid.ColumnStyles.Clear();
grid.ColumnStyles.Add(_firstFixed ? new ColumnStyle(SizeType.Absolute, _firstSize) : new ColumnStyle(SizeType.Percent, 33.33F));
grid.ColumnStyles.Add(new ColumnStyle(SizeType.Absolute, _secondSize));
grid.ColumnStyles.Add(_thirdFixed ? new ColumnStyle(SizeType.Absolute, _thirdSize) : new ColumnStyle(SizeType.Percent, 33.33F));
}
}
And my custom designer:
internal class CustomGridControlDesigner : ParentControlDesigner
{
public override void Initialize(IComponent component)
{
base.Initialize(component);
EnableDesignMode((Control as CustomGrid).Panel1, "Panel1");
base.Initialize(component);
EnableDesignMode((Control as CustomGrid).Panel2, "Panel2");
base.Initialize(component);
EnableDesignMode((Control as CustomGrid).Panel3, "Panel3");
base.Initialize(component);
EnableDesignMode((Control as CustomGrid).Panel4, "Panel4");
}
}
Now I can add controls to those panels, but I must add nested panel to all of my panels to be able to use align tool (blue lines):
Also how can I hide all properties of those 4 panels? Right now I can click on every one of them and change every property.

Idea is to have control that will become layout (template)
You are running into well-known limitations in design-time support, it just doesn't work very well anymore when it needs to deal with inherited or encapsulated controls. You are also well on your way creating a UI that's top-heavy with windows and will perform poorly at runtime. You created at least one rock in the road by declaring the control members private, as it behooves, the designer cannot deal with that since it needs to observe accessibility so cannot generate code that changes any of their properties.
I strongly recommend you instead set out to do what you in fact intended to accomplish, actually create an item template. Fairly well supported in Visual Studio with the File + Export Template command. Which give the user a cookie-cutter UserControl or Form to start out with that does not need a custom designer. And all the flexibility he might want to tweak your base design when needed, greatly encouraging re-usability of your design. Maybe you don't like to give the user this flexibility, creating a designer that removes capabilities is a lot easier than one that adds them. I don't recommend you actually do this, good odds you'll get a bunch of support requests that ask for adding them back :)

Related

Handling events across different classes using C#

I have a property defined in Class A. When the property is changed then i need to raise an event. Another class B should respond to this event and do something. I have done something like this:
Code:
Class A{
string variable = "test";
public delegate void EventHandler(object sender, EventArgs args);
public static event EventHandler ThrowAddEvent = delegate { };
public static event EventHandler ThrowRemoveEvent = delegate { };
public String Name { get; set; }
public int Select { get; set; }
public Window Formref1 { get; set; }
public bool IsSelected
{
get { return IsSlctd; }
set
{
IsSlctd = value;
if (value)
{
ThrowAddEvent(this, new EventArgs());
}
else
{
ThrowRemoveEvent(this, new EventArgs());
}
}
}
}
Another class which is responding to this event is defined as follows:
Class B{
public B(ParsedResult _result)
{
InitializeComponent();
if (_result != null)
{
this.Result = _result;
PopulateColumns1();
DataGrid1.Items.Clear();
DataGrid1.ItemsSource = Populatevariables();
}
}
public void PopulateColumns1()
{
DataGridTextColumn Colvar = new DataGridTextColumn();
Colvar.Header = "Variables";
Colvar.Binding = new Binding("Name");
DataGrid1.Columns.Add(Colvar);
DataGridTemplateColumn Col = new DataGridTemplateColumn();
Col.Header = "Select";
DataTemplate dd = new DataTemplate();
FrameworkElementFactory FF = new FrameworkElementFactory(typeof(CheckBox));
FF.SetBinding(CheckBox.BindingGroupProperty, new Binding("Select"));
FF.SetBinding(CheckBox.IsCheckedProperty, new Binding("IsSelected") { UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged });
FF.SetValue(FrameworkElement.HorizontalAlignmentProperty, HorizontalAlignment.Center);
dd.VisualTree = FF;
Col.CellTemplate = dd;
DataGrid1.Columns.Add(Col);
}
private List<A> PopulateVariables()
{
CheckBox cb = new CheckBox();
List<A> CharList = new List<A>();
Result.GetCharacteristicList.MoveNext();
IEnumerator<A2LCharacteristic> enumeratorlist = Result.GetCharacteristicList;
for (int i = 0; enumeratorlist.MoveNext(); i++)
{
CharList.Add(new A() { Name = enumeratorlist.Current.Name, Select = i, Formref1 = this});
}
enumeratorlist.Reset();
return CharList;
}
private void OKBtn_Click(object sender, RoutedEventArgs e)
{
A Instance_A = new A();
Instance_A.ThrowAddEvent += (sender1, args) => { Addvrbl(Instance_A.variable); };
Instance_A.ThrowRemoveEvent += (sender2, args) => { RmvVrbl(Instance_A.variable); };
this.Close();
}
public void Addvrbl(string vrbl)
{
if (!(vrbllist.Contains(vrbl)))
{
vrbllist.Add(vrbl);
}
}
public void RmvVrbl(string vrbl)
{
if ((vrbllist.Contains(vrbl)))
{
vrbllist.Remove(vrbl);
}
}
}
The problem is it is not going inside the method "AddVrbl" and "RmvVrbl". I have used the solution from here. Please help.
OK, instead of subscribing to the event of a new instance of A,which will never get triggered/published. When you initializing CharList, you have to subscribe to the event of each A item.
Something like:
for (int i = 0; enumeratorlist.MoveNext(); i++)
{
var obja=new A() { Name = enumeratorlist.Current.Name, Select = i, Formref1 = this};
obja.ThrowAddEvent += ...
obja.ThrowRemoveEvent += ...
CharList.Add(obja);
}
PS: Make sure you un-subscribe these events before removing an item from your CharList.

How to bind a combo box datasource to a form/listbox in windows forms?

I would like to get the form as datasource when i click combo box. How could i achieve this. Please give suggestion.
I've created a PopupComboBox class which inherits from the standard Windows Forms ComboBox. It has a Title property that you can set which will be used on the popup window when the combo is clicked.
public class PopupComboBox : ComboBox
{
private string title;
public string Title
{
get { return this.title; }
set { this.title = value; }
}
public PopupComboBox() : base()
{
}
public PopupComboBox (string title)
: base()
{
this.title = title;
}
protected override void OnMouseClick(MouseEventArgs e)
{
base.OnMouseClick(e);
// Show the popup form
var popup = new SelectItemForm(this.title, this);
var result = popup.ShowDialog(this);
if (result == DialogResult.OK)
{
// Select this item in the ComboBox
SelectedIndex = this.FindStringExact(popup.SelectedDisplay);
}
}
}
When you click on the combo, a popup form will come up (source code below for SelectItemForm). It uses the DataSource, ValueMember and DisplayMember of the parent PopupComboBox to populate a ListView with the list of items from the combo. When you click on OK, it will save the selected item in the SelectedValue and SelectedDisplay properties so that we can select that item in the ComboBox when the form closes.
public partial class SelectItemForm : Form
{
public object SelectedValue { get; private set; }
public string SelectedDisplay { get; private set; }
public SelectItemForm(string title, PopupComboBox parent)
:base()
{
InitializeComponent();
this.Text = title;
// Add items to the list
foreach (var item in parent.Items)
{
// Get the display and value member properties for this combo box
// and use them for the Code/Name columns in the popup form
var props = item.GetType().GetProperties();
var code = props.Where(p => p.Name == parent.ValueMember).Single().GetValue(item);
var name = props.Where(p => p.Name == parent.DisplayMember).Single().GetValue(item);
listView.Items.Add(new ListViewItem(
new string[] { code.ToString(), name.ToString() }));
}
}
private void btnOk_Click(object sender, EventArgs e)
{
if (listView.SelectedItems != null && listView.SelectedItems.Count > 0)
{
SelectedValue = listView.SelectedItems[0].Text;
SelectedDisplay = listView.SelectedItems[0].SubItems[1].Text;
DialogResult = DialogResult.OK;
}
else
{
MessageBox.Show(this, "Select an item first", "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
private void btnCancel_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Cancel;
}
}
Here is the designer part of the form, where you can see what properties I've changed for the ListView to look like it does:
partial class SelectItemForm
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.listView = new System.Windows.Forms.ListView();
this.btnOk = new System.Windows.Forms.Button();
this.btnCancel = new System.Windows.Forms.Button();
this.Code = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.Value = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.SuspendLayout();
//
// listView
//
this.listView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
| System.Windows.Forms.AnchorStyles.Left)
| System.Windows.Forms.AnchorStyles.Right)));
this.listView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
this.Code,
this.Value});
this.listView.FullRowSelect = true;
this.listView.GridLines = true;
this.listView.Location = new System.Drawing.Point(3, 3);
this.listView.MultiSelect = false;
this.listView.Name = "listView";
this.listView.Size = new System.Drawing.Size(432, 170);
this.listView.TabIndex = 0;
this.listView.UseCompatibleStateImageBehavior = false;
this.listView.View = System.Windows.Forms.View.Details;
//
// btnOk
//
this.btnOk.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnOk.Location = new System.Drawing.Point(272, 179);
this.btnOk.Name = "btnOk";
this.btnOk.Size = new System.Drawing.Size(75, 23);
this.btnOk.TabIndex = 1;
this.btnOk.Text = "OK";
this.btnOk.UseVisualStyleBackColor = true;
this.btnOk.Click += new System.EventHandler(this.btnOk_Click);
//
// btnCancel
//
this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.btnCancel.Location = new System.Drawing.Point(353, 179);
this.btnCancel.Name = "btnCancel";
this.btnCancel.Size = new System.Drawing.Size(75, 23);
this.btnCancel.TabIndex = 2;
this.btnCancel.Text = "Cancel";
this.btnCancel.UseVisualStyleBackColor = true;
this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click);
//
// Code
//
this.Code.Text = "Code";
this.Code.Width = 108;
//
// Value
//
this.Value.Text = "Name";
this.Value.Width = 296;
//
// SelectItemForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(440, 214);
this.Controls.Add(this.btnCancel);
this.Controls.Add(this.btnOk);
this.Controls.Add(this.listView);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "SelectItemForm";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
this.Text = "Title";
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.ListView listView;
private System.Windows.Forms.Button btnOk;
private System.Windows.Forms.Button btnCancel;
private System.Windows.Forms.ColumnHeader Code;
private System.Windows.Forms.ColumnHeader Value;
}
I've also created a small test form where you can test out the functionality of the PopupComboBox, using a small list of products. You'll need to add a PopupComboBox to the form in the designer, and call it comboPopup.
public partial class TestForm : Form
{
public class Product
{
public string Code { get; set; }
public string Name { get; set; }
}
public TestForm()
{
InitializeComponent();
}
private void TestForm_Load(object sender, EventArgs e)
{
var products = new List<Product>();
products.Add(new Product { Code = "0001", Name = "Coca Cola" });
products.Add(new Product { Code = "0002", Name = "Mountain Dew" });
products.Add(new Product { Code = "0003", Name = "Sprite Zero" });
comboPopup.DataSource = products;
comboPopup.DisplayMember = "Name";
comboPopup.ValueMember = "Code";
}
}

Cannot print a document with landscape orientation under Windows 8 (WPF, .NET 4.0)

I have some simple WPF (.NET 4.0) application that works differently on Windows 7 and Windows 8.1. If I print a document and select Landscape orientation in Print Dialog or in code as shown below, Windows 8.1 truncates it (on the printer) as it would be portrait. (I have not seen this effect before under Windows 7).
private void Print_Click(object sender, RoutedEventArgs e)
{
PrintDialog printDialog = new PrintDialog();
printDialog.PrintQueue = System.Printing.LocalPrintServer.GetDefaultPrintQueue();
printDialog.PrintTicket = printDialog.PrintQueue.DefaultPrintTicket;
printDialog.PrintTicket.PageOrientation = System.Printing.PageOrientation.Landscape;
if (printDialog.ShowDialog()??false)
{
//... ometed some code here
GridPaginator paginator = new GridPaginator(...);
printDialog.PrintDocument(paginator, "MyApp");
}
}
Any ideas, what was changed in Windows?
The trick to making this work is to set the PrintTicket.PageMediaSize property, using a newly-created PageMediaSize instance that specifies both the PageMediaSizeName and the width and height, with the dimensions translated to match the orientation.
PageMediaSizeName mediaSzNm = printDialog.PrintTicket.PageMediaSize.PageMediaSizeName.Value;
System.Windows.Size size = mediaSzNm.SizeInDips(printDialog.PrintTicket.PageOrientation.Value);
printDialog.PrintTicket.PageMediaSize = new PageMediaSize(mediaSzNm, size.Width, size.Height);
static public class PrintingHelper
{
public const int Dpi = 96;
// Get the page size, translated for page orientation
public static Size SizeInDips(this PageMediaSizeName name, PageOrientation orientation)
{
if (orientation == PageOrientation.Landscape)
return new Size(HeightInDips(name), WidthInDips(name));
return new Size(WidthInDips(name), HeightInDips(name));
}
public static double WidthInDips(this PageMediaSizeName name)
{
return WidthInInches(name) * Dpi;
}
public static double HeightInDips(this PageMediaSizeName name)
{
return HeightInInches(name) * Dpi;
}
public static double WidthInInches(this PageMediaSizeName name)
{
if ((name == PageMediaSizeName.NorthAmericaLegal) || (name == PageMediaSizeName.NorthAmericaLetter))
return 8.5;
return 0;
}
public static double HeightInInches(this PageMediaSizeName name)
{
if (name == PageMediaSizeName.NorthAmericaLegal)
return 14.0;
else if (name == PageMediaSizeName.NorthAmericaLetter)
return 11.0;
return 0;
}
}
Strange solution but works.
Get PrintDialog source code and save it in another class name. Delete internal references and ShowDialog method. (You can show dialog in your first object,then print with this)
My Edited Class :
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Printing;
using System.Security;
using System.Security.Permissions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Windows.Xps;
using System.Xml;
using MS.Internal.Printing;
using System.Windows.Xps.Serialization;
using System.Windows.Documents;
using System.Windows.Documents.Serialization; // WritingCompletedEventArgs
using MS.Internal.PresentationFramework;
namespace System.Windows.Controls
{
public class CustomPrintDialog
{
#region Constructors
[SecurityCritical]
public
CustomPrintDialog(
)
{
_dialogInvoked = false;
_printQueue = null;
_printTicket = null;
_isPrintableAreaWidthUpdated = false;
_isPrintableAreaHeightUpdated = false;
_pageRangeSelection = PageRangeSelection.AllPages;
_minPage = 1;
_maxPage = 9999;
_userPageRangeEnabled = false;
}
#endregion Constructors
#region Public properties
public PageRangeSelection PageRangeSelection
{
get
{
return _pageRangeSelection;
}
set
{
_pageRangeSelection = value;
}
}
public PageRange PageRange
{
get
{
return _pageRange;
}
set
{
if ((value.PageTo <= 0) || (value.PageFrom <= 0))
{
}
_pageRange = value;
if (_pageRange.PageFrom > _pageRange.PageTo)
{
int temp = _pageRange.PageFrom;
_pageRange.PageFrom = _pageRange.PageTo;
_pageRange.PageTo = temp;
}
}
}
public bool UserPageRangeEnabled
{
get
{
return _userPageRangeEnabled;
}
set
{
_userPageRangeEnabled = value;
}
}
public UInt32 MinPage
{
get
{
return _minPage;
}
set
{
if (_minPage <= 0)
{
}
_minPage = value;
}
}
public UInt32 MaxPage
{
get
{
return _maxPage;
}
set
{
if (_maxPage <= 0)
{
}
_maxPage = value;
}
}
#pragma warning restore 3003
public PrintQueue PrintQueue
{
[SecurityCritical]
get
{
if (_printQueue == null)
{
_printQueue = AcquireDefaultPrintQueue();
}
return _printQueue;
}
[SecurityCritical]
set
{
_printQueue = value;
}
}
public PrintTicket PrintTicket
{
[SecurityCritical]
get
{
if (_printTicket == null)
{
_printTicket = AcquireDefaultPrintTicket(this.PrintQueue);
}
return _printTicket;
}
[SecurityCritical]
set
{
_printTicket = value;
}
}
public
double
PrintableAreaWidth
{
get
{
if (((_isPrintableAreaWidthUpdated == false) && (_isPrintableAreaHeightUpdated == false)) ||
((_isPrintableAreaWidthUpdated == true) && (_isPrintableAreaHeightUpdated == false)))
{
_isPrintableAreaWidthUpdated = true;
_isPrintableAreaHeightUpdated = false;
UpdatePrintableAreaSize();
}
return _printableAreaWidth;
}
}
public
double
PrintableAreaHeight
{
get
{
if (((_isPrintableAreaWidthUpdated == false) && (_isPrintableAreaHeightUpdated == false)) ||
((_isPrintableAreaWidthUpdated == false) && (_isPrintableAreaHeightUpdated == true)))
{
_isPrintableAreaWidthUpdated = false;
_isPrintableAreaHeightUpdated = true;
UpdatePrintableAreaSize();
}
return _printableAreaHeight;
}
}
#endregion Public properties
#region Public methods
[SecurityCritical]
public
void
PrintVisual(
Visual visual,
String description
)
{
if (visual == null)
{
throw new ArgumentNullException("visual");
}
XpsDocumentWriter writer = CreateWriter(description);
writer.Write(visual);
_printableAreaWidth = 0;
_printableAreaHeight = 0;
_isPrintableAreaWidthUpdated = false;
_isPrintableAreaHeightUpdated = false;
_dialogInvoked = false;
}
[SecurityCritical]
public
void
PrintDocument(
DocumentPaginator documentPaginator,
String description
)
{
if (documentPaginator == null)
{
throw new ArgumentNullException("documentPaginator");
}
XpsDocumentWriter writer = CreateWriter(description);
writer.Write(documentPaginator);
_printableAreaWidth = 0;
_printableAreaHeight = 0;
_isPrintableAreaWidthUpdated = false;
_isPrintableAreaHeightUpdated = false;
_dialogInvoked = false;
}
#endregion Public methods
[SecurityCritical]
private
PrintQueue
AcquireDefaultPrintQueue()
{
PrintQueue printQueue = null;
try
{
try
{
LocalPrintServer server = new LocalPrintServer();
printQueue = server.DefaultPrintQueue;
}
catch (PrintSystemException)
{
//
// It is entirely possible for there to be no "default" printer. In this case,
// the printing system throws an exception. We do not want this to propagate
// up. Instead, returning null is fine.
//
printQueue = null;
}
}
finally
{
}
return printQueue;
}
[SecurityCritical]
private
PrintTicket
AcquireDefaultPrintTicket(
PrintQueue printQueue
)
{
PrintTicket printTicket = null;
try
{
try
{
if (printQueue != null)
{
printTicket = printQueue.UserPrintTicket;
if (printTicket == null)
{
printTicket = printQueue.DefaultPrintTicket;
}
}
}
catch (PrintSystemException)
{
//
// The printing subsystem can throw an exception in certain cases when
// the print ticket is unavailable. If it does we will handle this
// below. There is no real need to bubble this up to the application.
//
printTicket = null;
}
}
finally
{
}
//
// If the printing subsystem could not give us a print ticket either due to
// a failure or because a user/system default was not available, then just
// create a blank/empty one.
//
if (printTicket == null)
{
printTicket = new PrintTicket();
}
return printTicket;
}
[SecurityCritical, SecurityTreatAsSafe]
private
void
UpdatePrintableAreaSize(
)
{
PrintQueue printQueue = null;
PrintTicket printTicket = null;
PickCorrectPrintingEnvironment(ref printQueue, ref printTicket);
PrintCapabilities printCap = null;
if (printQueue != null)
{
printCap = printQueue.GetPrintCapabilities(printTicket);
}
// PrintCapabilities OrientedPageMediaWidth/Height are Nullable
if ((printCap != null) &&
(printCap.OrientedPageMediaWidth != null) &&
(printCap.OrientedPageMediaHeight != null))
{
_printableAreaWidth = (double)printCap.OrientedPageMediaWidth;
_printableAreaHeight = (double)printCap.OrientedPageMediaHeight;
}
else
{
// Initialize page size to portrait Letter size.
// This is our fallback if PrintTicket doesn't specify the page size.
_printableAreaWidth = 816;
_printableAreaHeight = 1056;
// PrintTicket's PageMediaSize could be null and PageMediaSize Width/Height are Nullable
if ((printTicket.PageMediaSize != null) &&
(printTicket.PageMediaSize.Width != null) &&
(printTicket.PageMediaSize.Height != null))
{
_printableAreaWidth = (double)printTicket.PageMediaSize.Width;
_printableAreaHeight = (double)printTicket.PageMediaSize.Height;
}
// If we are using PrintTicket's PageMediaSize dimensions to populate the widht/height values,
// we need to adjust them based on current orientation. PrintTicket's PageOrientation is Nullable.
if (printTicket.PageOrientation != null)
{
PageOrientation orientation = (PageOrientation)printTicket.PageOrientation;
// need to swap width/height in landscape orientation
if ((orientation == PageOrientation.Landscape) ||
(orientation == PageOrientation.ReverseLandscape))
{
double t = _printableAreaWidth;
_printableAreaWidth = _printableAreaHeight;
_printableAreaHeight = t;
}
}
}
}
[SecurityCritical, SecurityTreatAsSafe]
private
XpsDocumentWriter
CreateWriter(
String description
)
{
PrintQueue printQueue = null;
PrintTicket printTicket = null;
XpsDocumentWriter writer = null;
PickCorrectPrintingEnvironment(ref printQueue, ref printTicket);
try
{
if (printQueue != null)
{
printQueue.CurrentJobSettings.Description = description;
}
writer = PrintQueue.CreateXpsDocumentWriter(printQueue);
PrintDlgPrintTicketEventHandler eventHandler = new PrintDlgPrintTicketEventHandler(printTicket);
writer.WritingPrintTicketRequired +=
new WritingPrintTicketRequiredEventHandler(eventHandler.SetPrintTicket);
}
finally
{
}
return writer;
}
[SecurityCritical]
private
void
PickCorrectPrintingEnvironment(
ref PrintQueue printQueue,
ref PrintTicket printTicket
)
{
if (_dialogInvoked == false)
{
//
// If the dialog has not been invoked then the user needs printing permissions.
// If the demand succeeds then they can print. If the demand fails, then we
// tell them that the print dialog must be displayed first by throwing a dialog
// exception.
//
try
{
}
catch (SecurityException)
{
}
}
//
// If the default print queue and print ticket have not already
// been selected then update them now since we need them.
//
// NOTE: If this code gets called then we know the dialog has never
// been invoked but the above demand was satisfied. In this
// case we want to just pickup the user defaults.
//
if (_printQueue == null)
{
_printQueue = AcquireDefaultPrintQueue();
}
if (_printTicket == null)
{
_printTicket = AcquireDefaultPrintTicket(_printQueue);
}
//
// We should have valid print queue and print ticket objects to
// return now. As a note, a null PrintQueue is valid for this
// since the dialog will automatically pick up the user default
// printer for us.
//
printQueue = _printQueue;
printTicket = _printTicket;
}
#region Private data
/// <SecurityNote>
/// The PrintTicket is critical and not obtainable from a partial
/// trust application unless they can satisfy a printing permission
/// demand.
/// </SecurityNote>
[SecurityCritical]
private
PrintTicket _printTicket;
/// <SecurityNote>
/// The PrintQueue is critical and not obtainable from a partial
/// trust application unless they can satisfy a printing permission
/// demand.
/// </SecurityNote>
[SecurityCritical]
private
PrintQueue _printQueue;
/// <SecurityNote>
/// This variable is used to determine whether a user actually invoked
/// and dismissed the dialog prior to printing. In a partial trust app,
/// we can safely perform the necessary asserts to print as long as the
/// user said printing was okay.
/// </SecurityNote>
[SecurityCritical]
private
bool _dialogInvoked;
private
PageRangeSelection _pageRangeSelection;
private
PageRange _pageRange;
private
bool _userPageRangeEnabled;
private
UInt32 _minPage;
private
UInt32 _maxPage;
private
double _printableAreaWidth;
private
double _printableAreaHeight;
private
bool _isPrintableAreaWidthUpdated;
private
bool _isPrintableAreaHeightUpdated;
#endregion Private data
#region Internal classes
internal class PrintDlgPrintTicketEventHandler
{
#region Constructor
/// <SecurityNote>
/// Critical - PrintTicket argument is critical because it is defined in the none APTCA assembly ReachFramework.dll
/// TreatAsSafe - PrintTicket type is safe
/// </SecurityNote>
[SecurityCritical, SecurityTreatAsSafe]
public
PrintDlgPrintTicketEventHandler(
PrintTicket printTicket
)
{
_printTicket = printTicket;
}
#endregion Constructor
#region Public Methods
/// <SecurityNote>
/// Critical - Makes use of PrintTicket type which is critical because it is defined in the none APTCA assembly ReachFramework.dll
/// - Makes use of PrintTicketLevel type which is critical because it is defined in the none APTCA assembly ReachFramework.dll
/// TreatAsSafe - PrintTicket type is safe
/// </SecurityNote>
[SecurityCritical, SecurityTreatAsSafe]
public
void
SetPrintTicket(
Object sender,
WritingPrintTicketRequiredEventArgs args
)
{
if (args.CurrentPrintTicketLevel == PrintTicketLevel.FixedDocumentSequencePrintTicket)
{
args.CurrentPrintTicket = _printTicket;
}
}
#endregion Public Methods
#region Private Data
private
PrintTicket _printTicket;
#endregion Private Data
};
#endregion Internal classes
}
}
Usage
var pd = new CustomPrintDialog
{
PrintQueue = new PrintQueue(new PrintServer(), "THERMAL Receipt Printer"),
PrintTicket = { PageOrientation = PageOrientation.Portrait }
};
pd.PrintVisual(this, "asdsa");
Can anyone explain how it works?

How do I provide designer support to a TabControl residing in a UserControl, so that I can drag/drop controls onto tab pages?

I have a user control, which contains both a Panel and a TabControl. I enabled design-time support for both. I can drag/drop controls from the toolbox onto the Panel control that resides within the user control. I can also add and remove tab pages via the designer on the TabControl. However, I am not able to drag/drop any controls onto the tab pages themselves.
Below is the code generated source code for my user control:
partial class TestUserControl
{
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Component Designer generated code
private void InitializeComponent()
{
this.tabControl = new System.Windows.Forms.TabControl();
this.contentPanel = new System.Windows.Forms.Panel();
this.SuspendLayout();
//
// tabControl
//
this.tabControl.Dock = System.Windows.Forms.DockStyle.Fill;
this.tabControl.Location = new System.Drawing.Point(0, 0);
this.tabControl.Name = "tabControl";
this.tabControl.SelectedIndex = 0;
this.tabControl.Size = new System.Drawing.Size(306, 118);
this.tabControl.TabIndex = 0;
//
// contentPanel
//
this.contentPanel.Dock = System.Windows.Forms.DockStyle.Bottom;
this.contentPanel.Location = new System.Drawing.Point(0, 118);
this.contentPanel.Name = "contentPanel";
this.contentPanel.Size = new System.Drawing.Size(306, 73);
this.contentPanel.TabIndex = 0;
//
// TestUserControl
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.Controls.Add(this.tabControl);
this.Controls.Add(this.contentPanel);
this.Name = "TestUserControl";
this.Size = new System.Drawing.Size(306, 191);
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.TabControl tabControl;
private System.Windows.Forms.Panel contentPanel;
}
Below is the source code I added to enable design-time support:
[Designer(typeof(TestUserControlDesigner))]
public partial class TestUserControl : UserControl
{
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public TabControl TabControl
{
get { return this.tabControl; }
}
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public Panel ContentPanel
{
get { return this.contentPanel; }
}
public TestUserControl()
{
InitializeComponent();
}
}
internal class TestUserControlDesigner : ParentControlDesigner
{
public override void Initialize(System.ComponentModel.IComponent component)
{
base.Initialize(component);
EnableDesignMode(
(this.Control as TestUserControl).TabControl, "TabControl");
EnableDesignMode(
(this.Control as TestUserControl).ContentPanel, "ContentPanel");
}
}
What do I need to do, so that I can drag/drop controls onto the tab pages of the TabControl?
You have to enable design mode on the existing tab pages as well:
internal class TestUserControlDesigner : ParentControlDesigner {
public override void Initialize(System.ComponentModel.IComponent component) {
base.Initialize(component);
var ctl = (this.Control as TestUserControl).TabControl as TabControl;
EnableDesignMode(ctl, "TabControl");
foreach (TabPage page in ctl.TabPages) EnableDesignMode(page, page.Name);
EnableDesignMode((this.Control as TestUserControl).ContentPanel, "ContentPanel");
}
}

TreeView in Winforms and focus problem

Can anyone please explain to my why the form in the code below gets out of focus when selecting a treenode in the tree? What should happen is that the form/button should get the focus when the tree disappears like the listview example but it doesn't.
Code example:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace FocusTest
{
public partial class Form1 : Form
{
#region Generated
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
System.Windows.Forms.ListViewItem listViewItem1 = new System.Windows.Forms.ListViewItem("Item1");
System.Windows.Forms.ListViewItem listViewItem2 = new System.Windows.Forms.ListViewItem("Item2");
System.Windows.Forms.ListViewItem listViewItem3 = new System.Windows.Forms.ListViewItem("Item3");
System.Windows.Forms.TreeNode treeNode1 = new System.Windows.Forms.TreeNode("Node0");
System.Windows.Forms.TreeNode treeNode2 = new System.Windows.Forms.TreeNode("Node1");
System.Windows.Forms.TreeNode treeNode3 = new System.Windows.Forms.TreeNode("Node2");
this.button1 = new System.Windows.Forms.Button();
this.listView1 = new System.Windows.Forms.ListView();
this.button2 = new System.Windows.Forms.Button();
this.treeView1 = new System.Windows.Forms.TreeView();
this.SuspendLayout();
//
// button1
//
this.button1.Location = new System.Drawing.Point(12, 12);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 0;
this.button1.Text = "button1";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// listView1
//
this.listView1.Items.AddRange(new System.Windows.Forms.ListViewItem[] {
listViewItem1,
listViewItem2,
listViewItem3
});
this.listView1.Location = new System.Drawing.Point(12, 41);
this.listView1.Name = "listView1";
this.listView1.Size = new System.Drawing.Size(121, 97);
this.listView1.TabIndex = 1;
this.listView1.UseCompatibleStateImageBehavior = false;
this.listView1.Visible = false;
this.listView1.SelectedIndexChanged += new System.EventHandler(this.listView1_SelectedIndexChanged);
this.listView1.View = View.List;
//
// button2
//
this.button2.Location = new System.Drawing.Point(310, 11);
this.button2.Name = "button2";
this.button2.Size = new System.Drawing.Size(75, 23);
this.button2.TabIndex = 2;
this.button2.Text = "button2";
this.button2.UseVisualStyleBackColor = true;
this.button2.Click += new System.EventHandler(this.button2_Click);
//
// treeView1
//
this.treeView1.Location = new System.Drawing.Point(310, 41);
this.treeView1.Name = "treeView1";
treeNode1.Name = "Node0";
treeNode1.Text = "Node0";
treeNode2.Name = "Node1";
treeNode2.Text = "Node1";
treeNode3.Name = "Node2";
treeNode3.Text = "Node2";
this.treeView1.Nodes.AddRange(new System.Windows.Forms.TreeNode[] {
treeNode1,
treeNode2,
treeNode3});
this.treeView1.Size = new System.Drawing.Size(121, 97);
this.treeView1.TabIndex = 3;
this.treeView1.Visible = false;
this.treeView1.AfterSelect += new System.Windows.Forms.TreeViewEventHandler(this.treeView1_AfterSelect);
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(760, 409);
this.Controls.Add(this.treeView1);
this.Controls.Add(this.button2);
this.Controls.Add(this.listView1);
this.Controls.Add(this.button1);
this.Name = "Form1";
this.Text = "Form1";
this.ResumeLayout(false);
}
#endregion
private System.Windows.Forms.Button button1;
private System.Windows.Forms.ListView listView1;
private System.Windows.Forms.Button button2;
private System.Windows.Forms.TreeView treeView1;
#endregion
public Form1()
{
InitializeComponent();
}
#region TreeView
private void button2_Click(object sender, EventArgs e)
{
ToggleTreeView();
}
private void ToggleTreeView()
{
if (treeView1.Visible)
{
Controls.Remove(treeView1);
treeView1.Visible = false;
}
else
{
Controls.Add(treeView1);
treeView1.Size = new Size(300, 400);
treeView1.Location = PointToClient(PointToScreen(new System.Drawing.Point(button2.Location.X, button2.Location.Y + button2.Height)));
this.treeView1.BringToFront();
treeView1.Visible = true;
treeView1.Select();
}
}
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
ToggleTreeView();
}
#endregion
#region ListView
private void button1_Click(object sender, EventArgs e)
{
ToggleListView();
}
private void ToggleListView()
{
if (listView1.Visible)
{
Controls.Remove(listView1);
listView1.Visible = false;
}
else
{
Controls.Add(listView1);
listView1.Size = new Size(300, 400);
listView1.Location = PointToClient(PointToScreen(new System.Drawing.Point(button1.Location.X, button1.Location.Y + button1.Height)));
this.listView1.BringToFront();
listView1.Visible = true;
listView1.Select();
}
}
private void listView1_SelectedIndexChanged(object sender, EventArgs e)
{
if (listView1.Visible)
ToggleListView();
}
#endregion
}
}
Here is the problem and the fix.
TreeView re-grabs focus on Ctrl+Click
I can't explain why the form loses focus, but the problem seems to be the Controls.Remove(treeView1); line. If you remove the Controls.Remove and Controls.Add lines, then it seems to behave better.
Is there a reason why you are removing the treeView from the list of control? Just setting the visibility flag to false will cause the treeView to disappear after the user makes their selection.
EDIT:
In response to your comment:
My guess is that after treeView1_AfterSelect is called, the TreeView is setting focus to itself. Which in your code is impossible because you've removed the control from the form.
To test this theory, I added a timer, replaced the code with:
private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
{
timer1.Enabled = true;
timer1.Start();
}
private void timer1_Tick(object sender, EventArgs e)
{
ToggleTreeView();
timer1.Stop();
timer1.Enabled = false;
}
Now it works fine. So I'm guessing that the TreeView is calling this.Focus after it has fired the AfterSelect event. (That is just a guess, maybe someone else knows more about the internals them me:) )
And the reason why this is working with the ListView, is that it does not set focus to itself after listView1_SelectedIndexChanged.

Resources