In the MainWindow constructor, I am registering an event handler:
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
pageViewDocText = new PageViewDocText();
framePageDocFieldDetail.Content = pageViewDocText;
pageViewDocText.NewPageIRPRO += new GabeLib.SearchCls.DocEventHandler(ViewIPRO);
}
protected void ViewIPRO(string IRPOlink) // ...
}
public partial class PageViewDocText : Page, INotifyPropertyChanged
{
public event GabeLib.SearchCls.DocEventHandler NewPageIRPRO;
private void btn_PageBreakNext(object sender, RoutedEventArgs e)
{
// this fires but NewPageIRPRO is null
if (NewPageIRPRO != null)
{
NewPageIRPRO("dummylink");
}
}
}
But in PageViewDocText, NewPageIRPRO is null
What am I doing wrong?
From PageViewDocText, I want to call MainWindow.ViewIPRO.
This event handler fires and is registered the line below pageViewDocText.NewPageIRPRO +=
App.StaticGabeLib.Search.NewDocIRPRO += new GabeLib.SearchCls.DocEventHandler(ViewIPRO);
Looks like you are calling an event from another class (not listed) and there is a missing delegate.
Try this code:
public partial class MainWindow : Window, INotifyPropertyChanged
{
public MainWindow()
{
InitializeComponent();
pageViewDocText = new PageViewDocText();
framePageDocFieldDetail.Content = pageViewDocText;
pageViewDocText.PageBreakNext += new PageBreakNext(ViewIPRO);
}
protected void ViewIPRO(string IRPOlink) // ...
}
public partial class PageViewDocText : Page, INotifyPropertyChanged
{
public delegate void PageBreakNext(string IRPOlink);
public event PageBreakNext PageBreak;
private void btn_PageBreakNext(object sender, RoutedEventArgs e)
{
// this fires but NewPageIRPRO is null
if (PageBreak != null)
{
PageBreak("dummylink");
}
}
}
Related
I have a user control(VCtrlDetails in the code below) that hosts a data grid(detailsGrid) which is private.
Now, i have this control loaded in another user control(UcResult_Details) and i want to handle grid selection changed event in this another user control.
public partial class VCtrlDetails : UserControl
{
public event EventHandler<bool> EnableEditTemplateButton;
private void InitializeComponent()
{
private System.Windows.Forms.DataGrid detailsGrid;
this.detailsGrid.SelectionChanged += new
System.EventHandler(this.detailsGrid_SelectionChanged);
}
private void detailsGrid_SelectionChanged(object sender, EventArgs e)
{
EnableEditButton?.Invoke(this, IsApproved());
}
public bool IsApproved()
{ }
}
public partial class UcResult_Details : UserControl
{
private readonly VCtrlDetails vCtrlDetails;
UcResult_Details()
{
//Need to subscribe to vCtrlDetails' grid selection changed event here in this ctor
}
}
I'm not that well versed with event handlers, so stuck with the solution as the grid object is private in the user control 'VCtrlDetails', so cannot directly do something like:
vCtrlDetails.detailsGrid.SelectionChanged += DetailsGrid_SelectionChanged
You need to bubble the event up and out of the VCtrlDetails class. You could do so by creating an event within the VCtrlDetails class and allowing your UcResult_Details class to subscribe to it.
public partial class VCtrlDetails : UserControl
{
public event EventHandler<bool> EnableEditTemplateButton;
public event EventHandler<EventArgs> DetailsGridSelectionChanged;
private void InitializeComponent()
{
private System.Windows.Forms.DataGrid detailsGrid;
this.detailsGrid.SelectionChanged += new
System.EventHandler(this.detailsGrid_SelectionChanged);
}
private void detailsGrid_SelectionChanged(object sender, EventArgs e)
{
EnableEditButton?.Invoke(this, IsApproved());
//Raise your custom event
DetailsGridSelectionChanged?.Invoke(this, e);
}
public bool IsApproved()
{
}
}
public partial class UcResult_Details : UserControl
{
private readonly VCtrlDetails vCtrlDetails;
UcResult_Details()
{
//Need to subscribe to vCtrlDetails' grid selection changed event here in this ctor
this.vCtrlDetails.DetailsGridSelectionChanged += new
EventHandler(this.vCtrlDetailsSelectionChanged);
}
private void vCtrlDetailsSelectionChanged(object sender, EventArgs e)
{
//Do whatever
}
}
I developed an app, where the user sects on order from a list. If the order is selected, the EditOrderWindow shows. From this window, the user can add items to the Order by. This is done in a sub dialog AddItemWindow. Works fine for the first order.
However, if a second order is edited, the AddItemWindow shows again after its been closed. For the third order edited it shows three times aso.
I couldn't figure out why this happens, and how to prevent it.
ViewModel
public class ViewModel
{
public ICommand EditOrderCommand { get; set; }
public ICommand AddItemCommand { get; set; }
public event EventHandler<int> EditOrder;
public event EventHandler<int> AddItem;
public event EventHandler<int> ItemAdded;
public ViewModel()
{
//Is fired when an item in the datagrid in Control OrderList is doubleclicked
EditOrderCommand = new ICommand();
EditOrderCommand.Executed += EditOrderCommand_Executed();
//Is fired when the users click on add in EditOrderWindow
AddItemCommand = new ICommand();
AddItemCommand.Executed += AddItemCommand_Executed();
}
private void EditOrderCommand_Executed(object sender, EventArgs e)
{
if (SelectedOrder != null)
{
EditOrder(this, SelectedOrder.Id);
}
}
private void AddItemCommand_Executed(object sender, EventArgs e)
{
AddItem(this, new EventArgs());
}
}
Control: OrderList
public partial class OrderList : UserControl
{
ViewModel vm;
public OrderList()
{
InitializeComponent();
//DataContext is set in xmal
vm = (ViewModel)this.DataContext;
vm.EditOrder += Vm_EditOrder;
}
private void Vm_EditOrder(object sender, int e)
{
EditOrderWindow s = new EditOrderWindow(vm);
s.ShowDialog();
s = null;
}
Window: EditOrderWindow
public partial class EditOrderWindow : Window
{
ViewModel vm;
AddItemWindow aiw;
public EditOrderWindow(ViewModel _vm)
{
InitializeComponent();
vm = _vm;
this.DataContext = vm;
vm.AddItem -= Vm_AddItem;
vm.AddItem += Vm_AddItem;
}
private void Vm_AddItem(object sender, EventArgs e)
{
if (aiw == null)
{
aiw = new AddItemWindow(vm);
}
aiw.ShowDialog();
aiw = null;
}
}
Window: AddItemWindow
public partial class AddItemWindow : Window
{
public AddItemWindow(ViewModel _vm)
{
InitializeComponent();
this.DataContext = _vm;
_vm.ItemAdded -= _vm_ItemAdded;
_vm.ItemAdded += _vm_ItemAdded;
}
private void _vm_ItemAdded(object sender, EventArgs e)
{
this.Close();
}
}
I have a usercontrol which have timer
public partial class Cumle : UserControl
{
private bool cond=false;
//Some Code....
private void timer2_Tick(object sender, EventArgs e)
{
//Some Code....
if(//some condition...)
cond=true;
}
}
I am working on windows form.I want to display a message box which shows me that cond is true.I want to make this stuff without using timer on Form.
public partial class Form1 : Form
{
//What I must write here?
}
As mentioned, you should use Events. I would go like this:
public partial class Cumle : UserControl
{
public event EventHandler ConditionChangedToTrue;
protected virtual void OnConditionChangedToTrue(EventArgs e)
{
if (ConditionChangedToTrue != null)
ConditionChangedToTrue(this, e != null ? e : EventArgs.Empty);
}
private void timer2_Tick(object sender, EventArgs e)
{
//Some Code....
if (true) // add your condition
{
cond = true;
OnConditionChangedToTrue(null);
}
}
}
public partial class Form1 : Form
{
private Cumle cumle = new Cumle();
public Form1()
{
InitializeComponent();
cumle.ConditionChangedToTrue+= Cumle_ConditionChangedToTrue;
}
private void Cumle_ConditionChangedToTrue(object sender, EventArgs e)
{
// add your event handling code here
throw new NotImplementedException();
}
}
You need to add a public event to your UserControl, and subscribe to it from your main form.
Something like this should do it:
public partial class Cumle : UserControl
{
public event Action<bool> ConditionChanged = delegate {};
private bool cond=false;
//Some Code....
private void timer2_Tick(object sender, EventArgs e)
{
//Some Code....
if(//some condition...)
{
cond=true;
ConditionChanged(cond);
}
}
}
Then in your form:
public partial class Form1 : Form
{
void SubscribeToConditionChanged()
{
myUserControl.ConditionChanged += ShowDlg;
}
void ShowDlg(bool condition)
{
MessageBox.Show("....");
}
}
I've followed this question and tried to build my solution. The problem is that 'UserControlButtonClicked' appears to be null! So 'UserControlButtonClicked(this, EventArgs.Empty)' inside the if, doesn't run, and the method 'addStepContent' in the parent page is never called.
UserControl 'StepsBar'
public sealed partial class StepsBar : UserControl
{
public event EventHandler UserControlAddStepContent;
[...]
public StepsBar()
{
this.InitializeComponent();
Image step_1 = new Image();
ButtonInfo step_1Info = new ButtonInfo();
step_1Info.Add((int)stepNumber.one, (int)stepStatus.normal);
step_1.Tag = step_1Info;
step_1.Source = setBackground((int)stepStatus.normal);
step_1.Tapped += stepTapped;
[...]
}
public void stepTapped(Object sender, RoutedEventArgs e)
{
[...]
if (step != null)
{
[...]
firePageEvent();
}
}
public void firePageEvent()
{
if (UserControlAddStepContent != null)
{
UserControlAddStepContent(this, EventArgs.Empty);
}
}
Parent Page
public Violation()
{
this.InitializeComponent();
StepsBar stepsBar = new StepsBar();
stepsBar.UserControlAddStepContent += new EventHandler(addStepContent);
}
private void addStepContent(object sender, EventArgs e)
{
CheckBox check_1 = new CheckBox();
check_1.Content = "Check me!";
bodyStackPanel.Children.Add(check_1);
}
This assumes that you want to use an existing delegate rather than make your own and you aren't passing anything specific to the parent page by event args.
In the user control's code-behind (adapt as necessary if not using code-behind or C#):
public partial class MyUserControl : System.Web.UI.UserControl
{
public event EventHandler UserControlButtonClicked;
private void OnUserControlButtonClick()
{
if (UserControlButtonClicked != null)
{
UserControlButtonClicked(this, EventArgs.Empty);
}
}
protected void TheButton_Click(object sender, EventArgs e)
{
// .... do stuff then fire off the event
OnUserControlButtonClick();
}
// .... other code for the user control beyond this point
}
In the page itself you subscribe to the event with something like this:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
// hook up event handler for exposed user control event
MyUserControl.UserControlButtonClicked += new
EventHandler(MyUserControl_UserControlButtonClicked);
}
private void MyUserControl_UserControlButtonClicked(object sender, EventArgs e)
{
// ... do something when event is fired
}
}
Solved. The problem was this, on the parent page.
StepsBar stepsBar = new StepsBar();
stepsBar.UserControlAddStepContent += new EventHandler(addStepContent);
The istance of StepsBar was not added to the page. D'OH!
So here's what I've done:
stepsBar.UserControlAddStepContent += new EventHandler(addStepContent);
and on the xaml of the parent page:
<local:StepsBar x:Name="stepsBar"/>
I have a issue with passing information from one wpf window to another. For some reason when main window is loaded nothing is set in the label, I need to be able to keep the data in a string to use for anything (label not important but shows what I mean)?
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
public string MyData { get; set; }
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
label1.Content = MyData;
}
public partial class LoginWindow : Window
{
public LoginWindow()
{
InitializeComponent();
}
private void button2_Click(object sender, RoutedEventArgs e)
{
string mytext = "blabla";
MainWindow fromloginwindow = new MainWindow();
fromloginwindow.Mydata = mytext;
}
Or am I doing this the wrong way round?
EDIT:
Please do not go on a tangent about the label its unimportant I need to be able to get and set a string for use anywhere in the MainWindow. Also the string "mytext" is also irrelevant as obviously I will not be setting the string this way.
It sounds like you are running into an event lifecycle issue; the calls to the Loaded event happen pretty quickly and thus, the chance to set the text has passed. Instead, what you should do is either:
1) Bind the Property to the Label in the XAML
public event PropertyChangedEventHandler PropertyChanged;
public MainWindow()
{
InitializeComponent();
DataContext = this;
}
protected string _myData = string.Empty;
public string MyData
{
get { return _myData; }
set { _myData = value; NotifyPropertyChanged("MyData"); }
}
protected void NotifyPropertyChanged(string propName)
{
var methods = PropertyChanged;
if(methods != null)
methods(this, new PropertyChangedEventArgs(propName));
}
<Label Content="{Binding MyData}" />
2) Set the control text via another method (or inside the property declaration):
public void SetLabel(string text)
{
label1.Content = text;
}
protected void button2_Click(object sender, RoutedEventArgs e)
{
MainWindow x = new MainWindow();
x.SetLabel("blabla");
}
The Loaded event occurs before you set MyData, change the code like this:
public partial class MainWindow : Window
{
public MainWindow(string data)
{
MyData = data
InitializeComponent();
}
Have you tried passing the value to the second window through the window's constructor?
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
public MainWindow(string data)
: this()
{
label1.Content = data;
}
}
public partial class LoginWindow : Window
{
public LoginWindow()
{
InitializeComponent();
}
private void button2_Click(object sender, RoutedEventArgs e)
{
string mytext = "blabla";
MainWindow fromloginwindow = new MainWindow(mytext);
}
}