First off, I'm new to WPF and C# so maybe the issue I have is really easy to fix. But I'm kinda stuck at the moment.
Let me explain my problem.
I have a WPF Window and two usercontrols (Controls and ContentDisplayer).
The usercontrol Controls, wich contains some buttons, is added in the XAML of the Window.
Nothing special here.
Window.XAML
<nv:Controls/>
Now, what I want to do is when a user is pressing a button in Controls, ContentDisplayer needs to be added to the Scatterview I have in my Window.
I solved the problem by adding the buttons to the Window, and not using the usercontrol Controls. But this is not what I want.
Window.XAML.CS
private static void Button_ContactChanged(object sender, ContactEventArgs e)
{
object ob = Application.LoadComponent(new Uri(
"NVApril;component\\XAML\\ContentDisplayer.xaml",
System.UriKind.RelativeOrAbsolute));
//Set a unique name to the UserControl
string name = String.Format("userControl{0}",
SurfaceWindow1_Scatterview.Items.Count);
UserControl userControl = ob as UserControl;
userControl.Name = name;
//Add the new control to the Scatterview
SurfaceWindow1_Scatterview.Items.Add(userControl);
SurfaceWindow1_Scatterview.RegisterName(name, userControl);
}
So the real question is: How do I add a usercontrol to the Window by pressing a button in an other usercontrol?
Thanks,
Toner
At the top of the window xaml add
xmlns:d="clr-namespace:SomeNamespace.Usercontrols"
where you these exist already, you can choose the namespace of your control from the intellesence list.
Then where you want to place the control type:
<d:yourusercontrolhere params />
and your usercontrols can be added there.
Within Controls expose an event that is fired when you want to add a new control.
public event EventHandler AddControl;
private void RaiseAddControl()
{
if (AddControl!= null)
{
AddControl(this, EventArgs.Empty);
}
}
Now sink that event in your Window
yourControl.AddControl += ContactChanged
In your window, it sounds like you need to add the event to the instances of Controls.
<local:ContentDisplayer>
...
<nv:Controls AddControl="ContactChanged"/>
...
Then in your ContactChanged event handler you can instantiate a new Controls control and add it to whatever collection you're using like in your Button_ContactChanged event handler above.
Let me know if you need further clarification.
I have no idea what you are trying to do your example,
So you have a control defined thus:
public partial class somecontrolname : UserControl
With your corresponding Xaml file
All you need to do to add it in code to your window is firstly you need a LayoutRoot such as Grid control in the window then just
[mylayoutcontrol].Children.Add(new somecontrolname());
Maybe I got wrong idea what you are trying to do, your example code doesn't make much sense to me, looks like you are trying to load the xaml source file
Related
I'm french, so sorry for my bad english... But I hope that you will help me ;)
I'm developing a soft in c# with lot of information store in DB, like information about people.
I want display these information with a beautiful UI, like that :
For that, I created :
a first panel in Visual
a class for create sub panel dynamically
I make a loop and for each person, I call a method "createPanel" with the information of each person, and these sub panels created are added to the parent panel. The ID of each person is store in the "tag" parameter of the sub panel.
All work fine, but I don't really know how to add event in each sub panel.
As you can see in the link above, the user can click on a bookmark, or a icon for show a menu (the round with 3 point = icon "menu").
My question is how to add event for each sub panel dynamically ? For example I want display a menu for each sub panel when I click on the icon "menu", get the id store in the "tag" of the sub panel, and show a new form for manage information.
Thx for your help, I can add my code if necessary :)
Make a own user control for the panels you want to display containing all the controls from the toolbox you need.
public partial class MyControl : UserControl
{
...
}
In "MyControl" you define events for all things that can happen and must be handled externally of the control. Same as e.g. "SelectedIndexChanged" for combobox.
Your control class would then look like this:
public partial class MyControl : UserControl
{
public event EventHandler<MyImportantEventA> OnImportantThingHappend;
//Event-Invoker
protected virtual void OnOnImportantThingHappend(MyImportantEventA e)
{
OnImportantThingHappend?.Invoke(this, e);
}
}
//Data of your event. Customize as you like/need.
public class MyImportantEventA : EventArgs
{
public string Message { get; set; }
}
When you add your control dynamically, bind to the event(s) of your control:
myUserControl.OnImportantThingHappend += DoSomethingWithEvent;
Things the control can handle it self, don't need to be exposed as events.
E.g.:
"Close" may be something that must be handled externally. You need to remove the control, rearange you controls etc.
"Show Details" probably is something that can be handled completely inside of your control. Your control shows a message box or a fancy tooltip.
I have a UserControl that is dynamically added to a FlowLayoutPanel. In that same UserControl I have a button to remove itself if the user wants it, obviously at runtime. To eliminate I mean not only to eliminate that tight button, but also the full UserControl that contains the button.
The code of when the UserControl are added dynamically at the moment is as follows:
private void agregaUC() {
UserControl1 UC = new UserControl1();
aux += 1;
UC.Tag = aux.ToString();
flowLayoutPanel2.Controls.Add(UC);
}
The code to eliminate this is on the side of the form, that is, where the UserControl are being added. The button event to remove the UserControl is thrown by code through the operator + =, then there I write the suggestions that you give me.
EDIT: Based on the sample of code you've added, I've modified the below code to work better with what you are looking for. You need to find out how to access the Tag of the control you're trying to remove.
Since you don't have a reference, then you should make sure that the .Tag property can be found, because then you can do something like
foreach (Control c in flowLayoutPanel2.Controls) {
if (c.Tag == "Aux") {
flowLayoutPanel2.Controls.Remove(c);
c.Dispose();
break;
}
}
EDIT
Reading through all the comments everywhere, it seems like this is what's happening. There is a UserControl, inside that user control is a Button (Delete) and the button's Click event is subscribed to by the window, and it's in this event handler that we're trying to remove the UserControl from flowLayoutPanel2
Based on these assumptions, your function should look like this:
void UserControl_Delete_Click(object sender, EventArgs e)
{
Button Delete = (Button)sender;
UserControl UC = (UserControl)Delete.Parent;
flowLayoutControl2.Controls.Remove(UC);
UC.Dispose();
}
This is assuming a lot about the internal structure of everything, as I don't have the code to confirm this will work. It will get you a long ways down the path, though, and should only need a little tweaking based on the actual structure of the UserControl.
You can try something like that.
this.Parent.Controls.Remove(this);
Control.Parent Property.
Remark: Setting the Parent property value to null removes the control from the Control.ControlCollection of its current parent control.
So
this.Parent = null;
Edit
The code is intended to be called from within the user control itself.
I am attempting to make a complete custom TabControl.
So far my code works perfectly, however when I'm viewing my TabControl in the Visual Studio designer, I cannot add Controls into the TabPage Control which is inside of the TabControl. When attempted, it just places the control on top of the TabControl.
Unless you are adding controls to the TabPage via programming it by hand, that is, not using Visual Studio's Designer, using the TabControl is pointless.
PasteBin Link to my Control's Code
Here are images of the tab control with different tabs selected:
(source: gyazo.com)
(source: gyazo.com)
As you can see from the above images, the button is not placed into the tab page's control collection, as it floats above the tab control.
You can Use Tabcontrol from Design Toolbox in form and place the controls as you want.Then add the piece of code provided below to your code this will work.
Suppose you have custom class as Use this code write the Constructor as given below.
internal class MyCustomTabControl
{
public MyCustomTabControl(TabControl tabControlPassed)
: base()
{
this.tabcontrol = tabControlPassed;
}
TabControl tabcontrol;
}
In the main form Initialization call MyCustomTabControl initialization after InitializeComponent() method. Pass the this.tabControl1 while initializing Custom tabcontrol.
public partial class TabForm : Form
{
public TabForm()
{
InitializeComponent();
MyCustomTabControl customTab = new MyCustomTabControl(this.tabControl1);
}
}
:)
I have a windows form and i dont want to make any other windows forms just one windows form and different user controls how can i change between user controls for example hide one and show the other user control programmatically ?
private void Btt_info_Click(object sender, EventArgs e)
{
Frm_Main frm_main = new Frm_Main();
frm_main.Controls["panel1"].Controls.Clear();
UC_Info uc_info = new UC_Info();
frm_main.Controls["panel1"].Controls.Add(uc_info);
}
i added this but it doesnt work
Add a container control (if I remember correctly, there's a containers section in the toolbox?), like a panel. Create usercontrols for what you want to dynamically switch around. So make like a 'HomePage' usercontrol and a 'LoginPage' usercontrol. Dynamically add the usercontrol that you want to display to the container. WHen you want, remove it from the container and add a different usercontrol:
Panel myPanel = new Panel();
LoginPage ctlLoginPage = new LoginPage();
HomePage ctlHomePage = new HomePage();
//add the loginpage to the panel first
myPanel.Controls.Add(ctlLoginPage);
...do stuff...
//remove whatever control is currently in the Panel
myPanel.Controls.Clear();
//add the other control, the HomePage control instead now
myPanel.Controls.Add(ctlHomePage);
..do other stuff...
I usually do it this way so you leave your form itself open to add common controls and stuff that might be shared between your different 'pages'.
EDIT: Note that I normally would add the panel in the designer and not create it dynamically in the code. This was just an example.
EDIT: The interaction between your mainform and usercontrols can be handled in a few different ways, and I am not saying that any of these is the correct method.
You create a static property for your Panel on the Mainform, so that
you can always access it to swap your controls around.
In this example I'll also add a static method for it
enum PanelControlsEnum {HomePage, LoginPage};
public static Panel MyContainerPanel {get;set;}
public static void SwitchPanelControls(PanelControlsEnum selControl){
..put your switch panels code here..
}
Then inside your usercontrol you call a predefined method, something like:
MainForm.SwitchPanelControls(PanelControlsEnum.HomePage);
Another method is to bind the button click event on your mainform
instead of inside the form.
Like This:
HomePage ctlHomePage = new HomePage();
ctlHomePage.Click += MyClickEvent;
myPanel.Controls.Add(ctlHomePage)
...
private void MyClickEvent(object sender, RoutedEventArgs e)
{
..switch user control code here...
}
Create a method that returns a UserControl object. Then put conditions in that method as to which control you want to load at a specific condition and then in your main form code.
UserControl control = GetControlFromMyMethod();
form1.Controls.Add(control);
where 'control' is the returned control from your method.
To remove the existing one you have to loop through the form1.Controls and find out the control and call 'Remove'.
Update:
Mike C has a better idea of adding a panel and loading your desired control on the panel as then it's easy to remove your control and you then don't have to loop through the forms controls to find it and then remove it.
Try this:
this.Controls.Clear();
usercontrol load = new usercontrol ();
this.Controls.Add(load);
load.Show();
you could try this it will definitely help you as it did helped me a lot it short and straight to the point hope that will help
I created a UserControl that contains a textbox. When I try to initialize the textbox in the constructor of the UserControl, with some text like this
public FileSelector()
{
InitializeComponent();
TB_FolderPath.Text = #"c:\tmp\Test\";
}
I get an error in the MainWindow.xaml
Cannot create an instance of "FileSelector".
When I remove the row
TB_FolderPath.Text = #"c:\tmp\Test\";
I don't get the error, but of course an empty textbox.
Previously when I had the parts of the UserControl integrated in the MainWindow, there was also no problem.
I tried to create a simpler version of MainWindow using a UserControl to reproduce the problem, but in a simple case it works.
So, my questions.
What can be the cause of the problem?
How can I debug/analyze a problem like this systematically? I just get the this error in VisualStudio after building, without an explanation.
How/Where can I initialize the controls in a UserControl. In general, is the UserControl the right place to initialize the controls or would the MainWindow be also a possibility? (Is this possible at all?)
In WPF, unlike WinForms, the controls are not initialized completely after InitializeComponent(). Hence the uninitialized/unloaded controls throw errors.
You need to write handler to capture the Loaded event of the control.
Read Object Lifetime Events.
Get some more detailed info here.
Example (partially taken from OP's code):
public FileSelector()
{
InitializeComponent();
TB_FolderPath.Loaded += delegate { TB_FolderPath.Text = #"c:\tmp\Test\"; }
}