I use a TabControl in one of my classes. However, I don't want to bloat this class and put all the code in it, as well as all the XAML for the TabItems.
After some Googling I've come up with the UserControl. So I created a UserControl for every TabItem, with the C# code of the TabItem in this UserControl.
The problem here, is that I need to transfer some data from my parent window (the one containing the TabControl) to the UserControls, to correctly display the data needed for that tab.
I created the UserControl in XAML and the code is like this:
<TabItem Name="userTab" Header="Gebruikers" HorizontalAlignment="Stretch">
<local:UserTabControl x:Name="userTabPanel"/>
</TabItem>
This is the constructor code for my UserControl:
public UserTabControl() {
setUsersView(); // NEED DATA FOR THIS
setUserData((User)usersView.SelectedItem);
InitializeComponent();
}
This is the class variable in the UserControl that needs a variable from the parent window: private static Parser m_config;
When I run this, I get a compile error saying :
"Object reference not set to an instance of an object."
pointing to the XAML line where I create my UserControl.
So, the conclusion here is I am yet unable to pass the variable to the UserControl and would like to have some suggestions or hints or guidance on how to do it in this case. Where am I going wrong here in achieving the required functionality ?
Im not sure that its the best way to do so, but for me it worked well.
For start I create CustomUserControl Class that inherit from UserControl with constractor that get his parent Form as an attribute like this:
public partial class CustomUserControl : UserControl
{
MainForm parentForm;
public CustomUserControl(MainForm mainForm)
{
parentForm = mainForm;
}
...
...
private void doSomthing()
{
parentForm.MainFormMember = 1;
}
}
And in the MainForm:
public partial class MainForm : Form
{
private int MainFormMember{ get; set; }
private CustomUserControl customUserControl;
public MainForm()
{
InitializeComponent();
// Create and add the CustomUserControl manually and not from ToolBox
customUserControl = new CustomUserControl(this);
this.Controls.Add(customUserControl);
}
...
...
}
In this way you can access the Form components from the UserControl
Related
I have a main form that acts as a "Wizard" for a bunch of different user controls. I have one user control with relatively basic operations, and I am trying to create a new user control that inherits this basic user control.
However, the base user control has a variable containing the main form (so the user control can access the wizard control functions in the main form). When I create a new "inherited user control" the Designer complains that the reference to the main for has not been set to an instance of the object. I set the reference to the MainForm during runtime when I create an instance of the base user control.
Is there a way to make this work? Below is some simplified code demonstrating my problem.
MainForm.cs:
public partial class MainForm : Form
{
public string exampleString = "From MainForm";
public MainForm()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
BaseControl base = new BaseControl();
base.mainForm = this;
{
}
BaseControl.cs
public partial class BaseControl : UserControl
{
public MainForm mainForm { get; set;}
public TestPanel()
{
InitializeComponent();
string needed = mainForm.exampleString; //Object reference not set to an instance of an object here
}
}
So when I try to create a user control that inherits BaseControl through Solution -> Add -> New Item -> Inherited User Control and select BaseClass, the designer complains of the "Object reference not set to an instance of an object" error at the string needed = mainForm.exampleString line in BaseControl.cs.
Any help with this would be greatly appreciated. Hopefully this is enough information for you to understand what I am trying to do.
Thanks.
The code which you shared will not work, neither at run-time nor in design-time.
You are trying to use mainForm.exampleString in constructor of BaseControl while mainForm will be assigned just after creating an instance of BaseControl.
In such cases, specially when you want to have design-time support, you can derive from ISupportInitialize interface and override BeginInit and EndInit.
Example
The following control implements ISupportInitialize. If you drop an instance of the control on the form, at run-time, it tries to find the parent form and if it was MainForm tries to use public members of the MainForm:
using System.ComponentModel;
using System.Windows.Forms;
public class MyControl : Control, ISupportInitialize
{
public void BeginInit()
{
}
public void EndInit()
{
var parent = this.FindForm() as MainForm;
if (parent != null)
{
//Access to MainForm members
}
}
}
This is just an example that shows how to use ISupportInitialize. In action, it's not a good idea to have a dependency to a specific type of parent form. A better idea as already mentioned in Jimi's comment is relying on interfaces. For example you can have a property of ISomeInterface in your control. The interface should contain the methods or properties which you want to have for the parent of your control. Then implement the interface in some forms. Then after you dropped an instance of your control at run-time or design-time, assign the form to the property.
I've a problem with two user controls, first of all I've a user control named "Base" and I want to inherit it from another user control named "MyControl" but the "Base" control is a partial class and the user control "MyControl" just have a public class, so I use a partial class in "MyControl", and I use an ElementHost to show "MyControl" but I've the error "Cannot implicity convert type MyControl to System.Windows.UIElement".
I try to add "MyControl" as a Child but it shows that error.
Help!
Edit:
The clases looks like:
public partial class Base : UserControl
{
}
public partial class MyControl : Base
{
}
And I want to do something like this:
public addControl()
{
ElementHost _host = new ElementHost();
_host.Dock = Dockstyle.Fill;
_host.Child = _myControl;
panel.Control.Add(_host);
}
The error is at _host.Child = _myControl;. At this point the object _myControl is initialized.
Does it look something like?
public partial class Base : UIElement
{
}
public class myControl : Base
{
}
I'm not sure what you mean by
and I use an ElementHost
however, my guess is that you are trying to cast myControl as a ElementHost, but it isn't one.
Or myControl doesn't implement something that is required from UIElement.
Let me know if that helps.
I have a class called AppViewModel, this class it's responsible to control the screens. AppViewModel extends my BaseConductor:
public class BaseConductor : Conductor<Screen>.Collection.OneActive
{
...
}
Then, I call a viewmodel (UserControl) on the constructor of AppViewModel:
this.ActivateItem(new FirstViewModel());
On FirstViewModel, after the user clicks on a button I want to open SecondViewModel and close the FirstViewModel:
var conductor = this.Parent as IConductor;
conductor.DeactivateItem(this, true);
conductor.ActivateItem(new SecondViewModel(param));
I already tried to do this:
((IApp)this.Parent).ActivateItem(new SecondViewModel(param));
TryClose();
SecondViewModel extends my BaseScreen:
public class BaseSceen : Screen
{
...
}
I want to close the FirstViewModel, because on the FirstViewModel and SecondViewModel I have shortcuts. When I'm with the SecondViewModel opened I hit a shortcut, and the method that is executed it's from FirstViewModel. So, the FirstViewModel still running.
How can I close the FirstViewModel, and avoid this problem with shortcuts?
Thanks!
Do you really need to use Conductor<T>.Collection.OneActive? You can just use Conductor<T> so that activating an item will automatically deactivate and close the previously active item. And also, is it required that the button/action pair reside in the FirstViewModel? I suggest that you just put those in the AppViewModel and let it orchestrate the navigation and activation/deactivation of the two child screens.
public AppViewModel : Conductor<Screen>
{
public void AppViewModel()
{
ActivateItem(new FirstViewModel());
}
public void ActivateSecondViewModel()
{
// FirstViewModel will automatically be deactivated
// and closed since we are using plain Conductor<T>
ActivateItem(new SecondViewModel());
}
}
I found it! The shortcut event was attached to the window, not to the usercontrol.
So, event when usercontrol was ended the event still "attached" to the window. Now, I added an method that is called when UserControl is Unloaded, to "deattach" the event.
Bad mistake!
I'm currently developing a chat client/server with a WPF visual interface. One of the main function in the MainWindow class is designed to write a message in a richbox in the related WPF.
public partial class MainWindow : Window
{
// VU Window
public static MainWindow vuClient;
// VU Initialization
public MainWindow()
{
InitializeComponent();
vuClient = this;
}
static public void writeChat(User pUser, String pMessage)
{
...
// Writing in the richbox
vuClient.vuChatBox.Document.Blocks.Add(formatedMessage);
}
}
The problem is that if I call writeChat() in the MainWindow() function or through an event (onclick for example) everything works as attended, but if I try to call this function via an other class nothing happens! I don't even have an error. Do you have any clue about that issue?
No need to maintain the object "vuClient". Because writeChat is a static method.
You can directly called like below
MainWindow.writeChat();
you can't use an UI element or a function in some other class. you need to make a Delegate with an event. with the help of this event you can update your UI accordingly.
I've tried looking this up and I couldn't find anything that I understood.
But what I'm trying to do is create a class with all my functions in, then call it from the parent form.
And one of these functions contains adding controls to the parent form, but I cannot find out how to do this, can somebody help me please and explain it along the way?
Many thanks,
Jarrod
Typically, I'd just add a reference to the parent form in the lower class and initialize it in the constructor. Something like this:
public form MyForm : Form
{
Foo myFoo;
public MyForm()
{
this.myFoo = new Foo(this);
}
}
public class Foo
{
private MyForm parentForm;
public Foo(MyForm parent)
{
parentForm = parent;
}
}
Then you can reference the parent form and manipulate it how you wish. It also works for static classes, too.
Try this;
In your class use this method to add controls to Parent form
public static void AddControl(Form ParentForm,Control control,Point location)
{
control.Location=location;//This is only to show you
Parent.Controls.Add(control);//how it can be done.You can replace this logic with yours
//but make sure to add this Parent.Controls.Add(control),where control will be the name of your Control.
}
Then whenever you need to add a control call the function as;
ClassName.AddControl(this,new TextBox(),new Point(10,10));//Change ClassName to your class's name.
Anything else please let me know.