My problem is that I want to use WPF expander object to host some winforms control. And the position that I'm going to use this is in my application's setting form. But, what I couldn't find is to add more than one control to it.
After a lot of searching for solution to my problem I just found this simple code that only add one control to the WPF expander object (I require more than one control to be added):
private void Form1_Load(object sender, EventArgs e)
{
System.Windows.Controls.Expander expander = new System.Windows.Controls.Expander();
expander.Header = "Sample";
WPFHost = new ElementHost();
WPFHost.Dock = DockStyle.Fill;
WindowsFormsHost host = new WindowsFormsHost();
host.Child = new DateTimePicker();
expander.Content = host;
WPFHost.Child = expander;
this.Controls.Add(WPFHost);
}
In this code the expander only hosts one control.
How should I customize it to host more than one control ?
Please help
Using a System.Windows.Forms.Panel as a container will help:
private void Form1_Load(object sender, EventArgs e)
{
System.Windows.Controls.Expander expander = new System.Windows.Controls.Expander();
System.Windows.Controls.Grid grid = new System.Windows.Controls.Grid();
expander.Header = "Sample";
ElementHost WPFHost = new ElementHost();
WPFHost.Dock = DockStyle.Fill;
Panel panel1 = new Panel();
DateTimePicker dtPicker1 = new DateTimePicker();
Label label1 = new Label();
// Initialize the Label and TextBox controls.
label1.Location = new System.Drawing.Point(16, 16);
label1.Text = "Select a date:";
label1.Size = new System.Drawing.Size(104, 16);
dtPicker1.Location = new System.Drawing.Point(16, 32);
dtPicker1.Text = "";
dtPicker1.Size = new System.Drawing.Size(152, 20);
// Add the Panel control to the form.
this.Controls.Add(panel1);
// Add the Label and TextBox controls to the Panel.
panel1.Controls.Add(label1);
panel1.Controls.Add(dtPicker1);
WindowsFormsHost host = new WindowsFormsHost();
host.Child = panel1;
expander.Content = host;
WPFHost.Child = expander;
this.Controls.Add(WPFHost);
}
Related
I'd like to use a stackpanel with two textblock that have two uris, inside a ContentDialog. The problem is that despite I set the property to Vertical, it has no effect and that's the visual result
private async void AboutButton_Click(object sender, RoutedEventArgs e)
{
TextBlock gHRepoTB = new TextBlock();
Hyperlink hyperlink1 = new Hyperlink();
Run run1 = new Run();
run1.Text = "View GitHub repository";
hyperlink1.NavigateUri = new Uri("https://www.google.com/");
hyperlink1.Inlines.Add(run1);
gHRepoTB.Inlines.Add(hyperlink1);
TextBlock privacyPolicyTB = new TextBlock();
Hyperlink hyperlink2 = new Hyperlink();
Run run2 = new Run();
run2.Text = "Privacy Policy";
hyperlink2.NavigateUri = new Uri("https://www.bing.com/");
hyperlink2.Inlines.Add(run2);
gHRepoTB.Inlines.Add(hyperlink2);
StackPanel aboutPanel = new StackPanel();
aboutPanel.Orientation = Orientation.Vertical;
aboutPanel.Children.Add(gHRepoTB);
aboutPanel.Children.Add(privacyPolicyTB);
ContentDialog aboutDialog = new ContentDialog();
aboutDialog.Title = "About";
aboutDialog.Content = aboutPanel;
aboutDialog.PrimaryButtonText = "Report a bug";
aboutDialog.PrimaryButtonClick += ReportBug_Click;
aboutDialog.PrimaryButtonStyle = App.Current.Resources["AccentButtonStyle"] as Style;
aboutDialog.CloseButtonText = "Close";
await aboutDialog.ShowAsync();
}
#mm8 showed how to fix your problem, however this is the result of unnecessary and unclear code.
Here are the things I changed:
I've changed a button with hyperlink layout to a hyperlinkbutton.
I've set the contents to just a string since in this case no more is needed.
Instead of manually setting a style to the primarybutton, I've specified the DefaultButton
By creating the dialog this way, you are less prone to making mistakes, others and yourself later on will be able to tell faster what's going on, and less temporary variables are introduced.
The code (You should be able to copy this code directly over your current eventhandler):
private async void AboutButton_Click(object sender, RoutedEventArgs e)
{
StackPanel aboutPanel = new StackPanel();
aboutPanel.Children.Add(
new HyperlinkButton
{
Content = "View GitHub repository",
NavigateUri = new Uri("https://www.google.com/")
});
aboutPanel.Children.Add(
new HyperlinkButton
{
Content = "Privacy Policy",
NavigateUri = new Uri("https://www.bing.com/")
});
var dlg = new ContentDialog
{
Title = "About",
Content = aboutPanel,
PrimaryButtonText = "Report a bug",
DefaultButton = ContentDialogButton.Primary,
CloseButtonText = "Close"
};
dlg.PrimaryButtonClick += ReportBug_Click;
await dlg.ShowAsync();
}
See the result below:
You add the second Hyperlink to the wrong TextBlock. It should be privacyPolicyTB.Inlines.Add(hyperlink2);:
TextBlock privacyPolicyTB = new TextBlock();
Hyperlink hyperlink2 = new Hyperlink();
Run run2 = new Run();
run2.Text = "Privacy Policy";
hyperlink2.NavigateUri = new Uri("https://www.bing.com/");
hyperlink2.Inlines.Add(run2);
privacyPolicyTB.Inlines.Add(hyperlink2); //<-- here
I need to show only the Month name on the MonthCalendar header title.
I looked at the MonthCalendar methods but there's no method for either customizing header or changing header title. Only the font colors could be changed.
From comments, a way by using System.Windows.Controls.Calendar
Screen copies (french)
Test code (C#/Winforms/VS 2015 on Windows 10)
(I added the references to be added in comments)
private System.Windows.Forms.TextBox textBox1;
private System.Windows.Controls.Calendar calendar1;
private void Form1_Load(object sender, EventArgs e)
{
// Add reference to PresentationFramework
calendar1 = new System.Windows.Controls.Calendar();
// Test Background
// Add reference to PresentationCore
// Add reference to WindowsBase
System.Windows.Media.LinearGradientBrush linearGradientBrush = new System.Windows.Media.LinearGradientBrush(System.Windows.Media.Colors.Cyan, System.Windows.Media.Colors.Blue, new System.Windows.Point(0, 0), new System.Windows.Point(0, 1));
calendar1.Background = linearGradientBrush;
// Container for Calendar
System.Windows.Controls.Canvas canvas = new System.Windows.Controls.Canvas();
System.Windows.Controls.Viewbox viewbox1 = new System.Windows.Controls.Viewbox();
viewbox1.StretchDirection = System.Windows.Controls.StretchDirection.Both;
viewbox1.Stretch = System.Windows.Media.Stretch.Fill;
viewbox1.MaxWidth = 260;
viewbox1.MaxHeight = 260;
viewbox1.Child = calendar1;
canvas.Children.Add(viewbox1);
// Test Event
calendar1.SelectedDatesChanged += calendar1_SelectedDatesChanged;
textBox1 = new System.Windows.Forms.TextBox();
textBox1.Location = new System.Drawing.Point(10, 280);
textBox1.Name = "textBox1";
textBox1.Size = new System.Drawing.Size(149, 20);
Controls.Add(textBox1);
// Test new Culture
// using System.Globalization;
CultureInfo cultureinfo = (CultureInfo.CurrentCulture.Clone() as CultureInfo);
cultureinfo.DateTimeFormat.YearMonthPattern = #"yyyy - MMMM";
//cultureinfo.DateTimeFormat.YearMonthPattern = #"MMMM";
System.Threading.Thread.CurrentThread.CurrentCulture = cultureinfo;
// Host for controls
// Add reference to WindowsFormsIntegration
// using System.Windows.Forms.Integration;
var elementHost = new ElementHost();
elementHost.Child = canvas;
Controls.Add(elementHost);
elementHost.Location = new System.Drawing.Point(10, 10);
elementHost.Size = new System.Drawing.Size(300, 300);
ClientSize = new System.Drawing.Size(280, 340);
CenterToScreen();
}
private void calendar1_SelectedDatesChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
textBox1.Text = calendar1.SelectedDate.ToString();
}
I want to control my form load event from another form.
my problem I create some winform control in form1 runtime, but the creation will controlled by form2.
I will read some data from user in form2 and when user enter specific text I will create winform control in form1.
I make some code to do that using from1 to create winform control in runtime.
private TextBox txtBox = new TextBox();
private Button btnAdd = new Button();
private ListBox lstBox = new ListBox();
private CheckBox chkBox = new CheckBox();
private Label lblCount = new Label();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
this.MaximizeBox = false;
this.MinimizeBox = false;
this.BackColor = Color.White;
this.ForeColor = Color.Black;
this.Size = new System.Drawing.Size(550, 550);
this.Text = "Test Create form in runtime ";
this.FormBorderStyle = FormBorderStyle.FixedDialog;
this.StartPosition = FormStartPosition.CenterScreen;
this.btnAdd.BackColor = Color.Gray;
this.btnAdd.Text = "Add";
this.btnAdd.Location = new System.Drawing.Point(90, 25);
this.btnAdd.Size = new System.Drawing.Size(50, 25);
this.txtBox.Text = "Text";
this.txtBox.Location = new System.Drawing.Point(10, 25);
this.txtBox.Size = new System.Drawing.Size(70, 20);
this.lstBox.Items.Add("One");
this.lstBox.Sorted = true;
this.lstBox.Location = new System.Drawing.Point(10, 55);
this.lstBox.Size = new System.Drawing.Size(130, 95);
this.chkBox.Text = "Disable";
this.chkBox.Location = new System.Drawing.Point(15, 190);
this.chkBox.Size = new System.Drawing.Size(110, 30);
this.lblCount.Text = lstBox.Items.Count.ToString() + " items";
this.lblCount.Location = new System.Drawing.Point(55, 160);
this.lblCount.Size = new System.Drawing.Size(65, 15);
this.Controls.Add(btnAdd);
this.Controls.Add(txtBox);
this.Controls.Add(lstBox);
this.Controls.Add(chkBox);
this.Controls.Add(lblCount);
}
How make the same thing from form2 ?
I don't know which kind of 'Control' you need. However in multiple forms environment, communication between forms is trivial. There are many ways to do communicate, like one can be as
Create public properties of type Form in your Parent form,
public Form propForm1 {get;set;}
When on menu item click you open form1, store it's object to that public property.
var form1 = New yourchildformname();
form1.MdiParent = this;
propForm1 = form1; // Add this line.
form1.Show();
Now every time when you will click an other button to open the form2, you will have propForm1 object, which you can use to set some data on that form.
EDIT:
On form2, you can access controls of form1 as
private void button1_Click(object sender, EventArgs e)
{
this.parent.propForm1.txtUserName = "Yokohama";
}
Remember the above code is on form2. Also set 'access modifier' property of txtUserName from private to public.
i have a Normal Panel in my windows form Application and i want to add a stack panel which is there in WPF inside it.
Stack Panel should Consists of 2 Expander Controls inside it.
i am using Element Host to Have the stack panel and expander Control in the windows form.
i am using the Following Code:
ElementHost WPF_Container = new ElementHost();
WPF_Container.AutoSize = true;
ElementHost WPF_Container1 = new ElementHost();
WPF_Container1 .AutoSize = true;
ElementHost StackPanelHost = new ElementHost();
Expander expander1 = new Expander();
expander1.Header = "Pipes";
Expander Expander2 = new Expander();
Expander2.Header = "Mountings";
uc1 uc1 = new uc1(); // Object Creation for User Control-1
uc2 uc2 = new uc2(); // Object Creation for User Control-2
StackPanel Stackpanel = new StackPanel();
Stackpanel.Orientation = System.Windows.Controls.Orientation.Vertical;
WindowsFormsHost host = new WindowsFormsHost();
host.Child = uc1 ;
WindowsFormsHost host2 = new WindowsFormsHost();
host2.Child = uc2;
expander1.Content = host;
Expander2.Content = host2;
Stackpanel.Children.Add(expander1);
Stackpanel.Children.Add(Expander2);
// WPF_Container.Child = expander1;
// WPF_Container1.Child = Expander2;
StackPanelHost.Child = Stackpanel;
panel1.Controls.Add(StackPanelHost); // Adding Stack Panel to my Winform Panel.
by using the above Code during Form Load Event no controls are getting added to my Windows form Panel.
How to Achieve the functionality
Here is an example of how you do it:
ElementHost host = new ElementHost();
StackPanel wpfPanel = new StackPanel();
host.Child = wpfPanel;
//panel1 is Windows Forms Panel
panel1.Controls.Add(host);
I recomend that you create the UI you need in a WPF user control and then add it to the ElementHost.
UPDATE:
ElementHost host = new ElementHost();
StackPanel wpfPanel = new StackPanel();
host.Child = wpfPanel;
//panel1 is Windows Forms Panel
panel1.Controls.Add(host);
var testButton = new System.Windows.Controls.Button(){Content = "test"};
wpfPanel.Children.Add(testButton);
Pay attention you are using the correct namespace as windows forms as also a Button Class
I am trying to create a windows application where I want to display a group of controls (Combo Box, Text Box and a button) on button click inside a panel.
I have created a code to create controls once but I want to create them again and again on button click one below another.
The code I am using is
public partial class Employee_PayHeads_add : Form
{
private TextBox txtBox = new TextBox();
private Button btnAdd = new Button();
private ComboBox combohead = new ComboBox();
public Employee_PayHeads_add()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
this.btnAdd.BackColor = Color.Gray;
this.btnAdd.Text = "Remove";
this.btnAdd.Location = new System.Drawing.Point(240, 25);
this.btnAdd.Size = new System.Drawing.Size(70, 25);
this.txtBox.Text = "";
this.txtBox.Location = new System.Drawing.Point(150, 25);
this.txtBox.Size = new System.Drawing.Size(70, 40);
this.combohead.Location = new System.Drawing.Point(10, 25);
panel1.Controls.Add(btnAdd);
panel1.Controls.Add(txtBox);
panel1.Controls.Add(combohead);
}
Also I want a vertical scroller in the panel if number controls overlap the space.
Thanks in advance
Inside the button click event create new objects, instead of using the one you declared before.
Try something like that:
public partial class Employee_PayHeads_add : Form
{
private TextBox txtBox = new TextBox();
private Button btnAdd = new Button();
private ComboBox combohead = new ComboBox();
private int txtBoxStartPosition = 150;
private int btnAddStartPosition = 240;
private int comboheadStartPosition = 10;
}
public Employee_PayHeads_add()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
TextBox newTxtBox = new TextBox();
Button newBtnAdd = new Button();
ComboBox newCombohead = new ComboBox();
newBtnAdd.BackColor = Color.Gray;
newBtnAdd.Text = "Remove";
newBtnAdd.Location = new System.Drawing.Point(btnAddStartPosition, 25);
newBtnAdd.Size = new System.Drawing.Size(70, 25);
newTxtBox.Text = "";
newTxtBox.Location = new System.Drawing.Point(txtBoxStartPosition, 25);
newTxtBox.Size = new System.Drawing.Size(70, 40);
newCombohead.Location = new System.Drawing.Point(comboheadStartPosition, 25);
panel1.Controls.Add(newBtnAdd);
panel1.Controls.Add(newTxtBox);
panel1.Controls.Add(newCombohead);
txtBoxStartPosition += 50;
btnAddStartPosition += 50;
comboheadStartPosition += 50;
}
I havent tried your code yet, but it shows that it is always creating the new controls on every click event, but as youo have specified the hardcoaded location for buttons, so it must be creating new controls overlapping each other. so you can change the location dynamically and hopefully it will work
If you want to add the controls again and again you have to create new ones. So rather than defining them in your form like that you have to:
private void button1_Click(object sender, EventArgs e)
{
Button btnAdd = new Button();
btnAdd.BackColor = Color.Gray;
btnAdd.Text = "Remove";
btnAdd.Location = new System.Drawing.Point(240, 25);
btnAdd.Size = new System.Drawing.Size(70, 25);
TextBox txtBox = new TextBox();
txtBox.Text = "";
txtBox.Location = new System.Drawing.Point(150, 25);
txtBox.Size = new System.Drawing.Size(70, 40);
ComboBox combohead = new ComboBox();
combohead.Location = new System.Drawing.Point(10, 25);
panel1.Controls.Add(btnAdd);
panel1.Controls.Add(txtBox);
panel1.Controls.Add(combohead);
}
Now you can remove those private declarations on top of your class.