I'm developing a C# and WPF app.
I have a WPF Page 'HomeView' with a UserControl 'CreateItem'. After I click a Button (which related function is Close()) inside the UserControl, I have to make the UserControl visibility collapsed and call a function 'ReloadAnalytics' in the Page code.
namespace iMP
{
public partial class CreateItem : UserControl
{
public CreateItem()
{
InitializeComponent();
}
private void Close(object sender, RoutedEventArgs e)
{
HomeView objHomeView= new HomeView();
objHomeView.CreateNewItemDisplayGrid.Visibility = Visibility.Collapsed;
objHomeView.InitializeAnalyticsOverview();
}
}
When I call this function, pressing the Button, nothing happens. (CreateNewItemDisplayGrid is the name of the UserControl in HomeView)
(HomeView namespace is iMP.Views and the public partial class is HomeView : Page)
Follow the structure below. I defined an event in usercontrol and use that event in the main form.
Try to match the code with your code
In UserControl
public partial class CreateItem : UserControl
{
public event ClickEventHandler CloseButtonClick;
public delegate void ClickEventHandler(object Sender, RoutedEventArgs e);
public CreateItem()
{
InitializeComponent();
}
private void Close(object sender, RoutedEventArgs e)
{
if (CloseButtonClick != null)
{
CloseButtonClick(this, e);
}
}
}
In HomeView
public partial class HomeView : Page
{
public HomeView()
{
InitializeComponent();
CreateItem userControl = new CreateItem();
this.Content = userControl;
userControl.CloseButtonClick += UserControl_CloseButtonClick;
}
private void UserControl_CloseButtonClick(object Sender, RoutedEventArgs e)
{
///...................................
this.CreateNewItemDisplayGrid.Visibility = Visibility.Collapsed;
///.......................
}
}
Related
This is my parent form:
public partial class ParentControl: UserControl
{
public ParentControl()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
ChildForm child= new ChildForm ();
child.Dock = DockStyle.Fill;
TabPage tabNewChild= new TabPage("Child");
tabNewChild.Controls.Add(child);
tabDetails.TabPages.Add(tabNewChild);
tabDetails.SelectedIndex = tabDetails.TabPages.IndexOf(tabNewChild);
}
void CloseTab()
{
\\Close the selected tab
}
}
This is my child usercontrol:
public partial class ChildForm : UserControl
{
public ChildForm ()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
\\Call the CloseTab in parent user control.
}
}
What is the optimal and proper way of implementing this?
I have researched about delegates and eventargs but cant decide what to use.
I have lots of modules that will be implemented in this way thats why I want to know the proper way of doing it. THanks a lot.
You can access to the Parent property of the ChildForm then cast it to ParentControl and call the CloseTab method:
public partial class ChildForm : UserControl
{
private void button1_Click(object sender, EventArgs e)
{
(Parent as ParentControl)?.CloseTab(this);
}
}
You may add the tab instance as method argument to close the good tab.
public partial class ParentControl: UserControl
{
public void CloseTab(ChildForm sender)
{
// close sender
}
}
A good solution is to create an event on your user control that is triggered when a close is requested:
public partial class ChildForm : UserControl
{
public ChildForm ()
{
InitializeComponent();
}
public event EventHandler CloseTabRequested;
protected virtual void OnCloseTabRequested(EventArgs e)
{
CloseTabRequested?.Invoke(this, EventArgs.Empty);
}
private void button1_Click(object sender, EventArgs e)
{
OnCloseTabRequested(EventArgs.Empty);
}
}
You can handle the event in the parent form:
public partial class ParentControl: UserControl
{
public ParentControl()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
ChildForm child= new ChildForm ();
child.Dock = DockStyle.Fill;
child.CloseTabRequested += ChildForm_CloseTabRequested;
TabPage tabNewChild= new TabPage("Child");
tabNewChild.Controls.Add(child);
tabDetails.TabPages.Add(tabNewChild);
tabDetails.SelectedIndex = tabDetails.TabPages.IndexOf(tabNewChild);
}
void ChildForm_CloseTabRequested(object sender, EventArgs e)
{
CloseTab((ChildForm)sender);
}
void CloseTab(ChildForm requestingForm)
{
\\Close the selected tab
}
}
With this solution the user control is not bound to a specific parent form for maximum reusability. It also avoids a dependency of the child form on the parent form, which is good design.
I have my MainWindow with a frame inside a Grid.
I want to load a Page1 inside the frame. Now I have a Button on this Page1. This Button should close Page1 and load Page2 in the frame. The second Page has also a button. With the button on Page2, I want to load Page1. And so on. If I would place the two buttons in the main window I can load both Pages, but I need the buttons separately on each page.
namespace PageTest
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
FrameContent.Content = new Page1();
}
}
}
namespace PageTest
{
public partial class Page1 : Page
{
public Page1()
{
InitializeComponent();
}
private void BtnLoadPage2_Click(object sender, RoutedEventArgs e)
{
}
}
}
namespace PageTest
{
public partial class Page2 : Page
{
public Page2()
{
InitializeComponent();
}
private void BtnLoadPage1_Click(object sender, RoutedEventArgs e)
{
}
}
}
You could use the fact a button click is a routed event to handle it in the parent frame.
<Frame Name="ParentFrame"
Button.Click="ParentFrame_Click"
>
</Frame>
Code
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
ParentFrame.Navigate(new Page1());
}
private void ParentFrame_Click(object sender, RoutedEventArgs e)
{
Button btn = e.OriginalSource as Button;
if(btn == null || btn.Tag == null)
{
return;
}
Page page = (Page)Activator.CreateInstance((Type)btn.Tag);
ParentFrame.Navigate(page);
}
}
Button in Page1:
<Button Width="100" Height="30"
Content="Go Page 2"
Tag="{x:Type local:Page2}"
/>
Page2:
<Button Width="100" Height="30"
Content="Go Page 1"
Tag="{x:Type local:Page1}"
/>
However. This would be considered unsuitable for a commercial app in all the teams I've worked. It is much more usual to use MVVM and viewmodel first navigation with usercontrols presented by contentcontrols.
You can put the code to swap pages on MainWindow.cs then you will need to define events on both pages like; PageSwapRequested. You will register to this event everytime a page is created and when a button is clicked it will trigger the event.
Something like this,
namespace PageTest
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var page1 = new Page1();
page1.PageSwapRequested += Page1_PageSwapRequested;
FrameContent.Content = page1;
}
private void Page1_PageSwapRequested(object sender, EventArgs e)
{
//TODO: swap pages and don't forget to remove Page1_PageSwapRequested event handler.
//page1.PageSwapRequested -= Page1_PageSwapRequested;
}
}
}
namespace PageTest
{
public partial class Page1 : Page
{
public event EventHandler PageSwapRequested;
private void OnPageSwapRequested()
{
this.PageSwapRequested?.Invoke(this, EventArgs.Empty);
}
public Page1()
{
InitializeComponent();
}
private void BtnLoadPage2_Click(object sender, RoutedEventArgs e)
{
OnPageSwapRequested();
}
}
}
namespace PageTest
{
public partial class Page2 : Page
{
public event EventHandler PageSwapRequested;
private void OnPageSwapRequested()
{
this.PageSwapRequested?.Invoke(this, EventArgs.Empty);
}
public Page2()
{
InitializeComponent();
}
private void BtnLoadPage1_Click(object sender, RoutedEventArgs e)
{
this.OnPageSwapRequested();
}
}
}
I want to change the Text of a Button in my "UserControl1" with a Button in my MainMenu's Grid. "UserControl1" is a Children of a Grid that is in another UserControl("UserControl2"). The "UserControl2" is a Child of a Grid that is in the MainWindow.
For better understanding:
MainWindow Code:
namespace UserControlTest
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
UserControl2 test = new UserControl2();
grd_Main.Children.Add(test);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
}
}
}
UserControl2 Code:
namespace UserControlTest
{
public partial class UserControl2 : UserControl
{
public UserControl2()
{
InitializeComponent();
UserControl1 uc1 = new UserControl1();
grd_ParentOfUserControl1.Children.Add(uc1);
}
}
}
Try this, i.e. you can get a reference to a UserControl by casting the elements in the Grid's Children collection:
private void Button_Click(object sender, RoutedEventArgs e)
{
UserControl2 uc2 = grd_Main.Children.OfType<UserControl2>().FirstOrDefault();
if (uc2 != null)
{
UserControl1 uc1 = uc2.grd_ParentOfUserControl1.Children.OfType<UserControl1>().FirstOrDefault();
if (uc1 != null)
{
uc1.theButton.Content = "the text...";
}
}
}
I've got a AddWindow to add new client, the MainWindow (which is always showed) and I want to send the information from Addwindow to ListBox in MainWindow (I mean i need to add new item to listbox).
Someone knows how can I do that?
You can do that with events of that object like this :
public partial class AddWindow : Window
{
public AddWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
if (Check != null)
Check(TextBox.Text);
}
public event Action<string> Check;
}
and in main window
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
AddWindow popup = new AddWindow();
popup.Check += popup_Check;
popup.Show();
}
void popup_Check(string obj)
{
ListBox.Items.Add(obj);
}
}
Is there a way to give a User Control custom events, and invoke the event on a event within the user control. (I'm not sure if invoke is the correct term)
public partial class Sample: UserControl
{
public Sample()
{
InitializeComponent();
}
private void TextBox_Validated(object sender, EventArgs e)
{
// invoke UserControl event here
}
}
And the MainForm:
public partial class MainForm : Form
{
private Sample sampleUserControl = new Sample();
public MainForm()
{
this.InitializeComponent();
sampleUserControl.Click += new EventHandler(this.CustomEvent_Handler);
}
private void CustomEvent_Handler(object sender, EventArgs e)
{
// do stuff
}
}
Aside from the example that Steve posted, there is also syntax available which can simply pass the event through. It is similar to creating a property:
class MyUserControl : UserControl
{
public event EventHandler TextBoxValidated
{
add { textBox1.Validated += value; }
remove { textBox1.Validated -= value; }
}
}
I believe what you want is something like this:
public partial class Sample: UserControl
{
public event EventHandler TextboxValidated;
public Sample()
{
InitializeComponent();
}
private void TextBox_Validated(object sender, EventArgs e)
{
// invoke UserControl event here
if (this.TextboxValidated != null) this.TextboxValidated(sender, e);
}
}
And then on your form:
public partial class MainForm : Form
{
private Sample sampleUserControl = new Sample();
public MainForm()
{
this.InitializeComponent();
sampleUserControl.TextboxValidated += new EventHandler(this.CustomEvent_Handler);
}
private void CustomEvent_Handler(object sender, EventArgs e)
{
// do stuff
}
}