I am working on a WPF application and I have a window with a grid in it and a few user controls. The problem arises when I add these user controls to the grid from the code behind (through C#),
// UserControlA is the user control with all the working content
var ucA = new UserControlA;
Grid.Children.Add(ucA);
There are two things that happen here, one is the user control is initialized, the second is any load events I have in the code behind of the user control also get fired.
The reason I have these load events like is because before the user control is presented to any employee then it should check for employee authorization, so instead of doing this
public partial class UserControlA : UserControl
{
public UserControlA()
{
IntializeComponent();
Authorize();
}
}
I do this:
public partial class UserControlA : UserControl
{
public UserControlA()
{
IntializeComponent();
}
private void UserControlA_Loaded(object sender, RoutedEventArgs e)
{
Authorize();
}
}
I only want to know why the Loaded event is fired without any reason?
Related
I am building a WPF application with the aid of MVVM light and Unity.
I have a ribbon control in the main form, with one tab without tab category, and two tabs in a tab category. User control 3 includes user control 2 and user control 1.
I would like to make visible the Tab Category and tabs 2 and 3 when I click in user control 2 and make them invisible when click in user control 3 or 1.
I confused a little bit with the event handling in mvvm structure.
I would like to do this properly with the MVVM rules. Could you give me an example or some really helpful directions how to do it?
Check how it looks like
Your Ribbon or tabs for that matter, should be backed up by a ViewModel, let's say TabCategoryViewModel or Tab2ViewModel and Tab3ViewModel. Inside these ViewModels you inject the IMessanger service (of course register it before if not already done) and create a POCO event message, like SelectedViewMessage
public class SelectedViewMessage
{
public string ViewName { get; set; }
}
Inside your TabCategoryViewModel you would register to listen to this message
public class TabCategoryViewModel : ViewModelBase
{
public readonly IMessanger messageService;
public TabCategoryViewModel(IMessanger messageService)
{
if(messageService == null)
{
throw ArgumentNullException("messageService");
}
this.messageService = messageService;
this.messageService.Register<GoToPageMessage>(this, OnSelectedViewChanged);
}
protected void OnSelectedViewChanged(SelectedViewMessage message)
{
this.IsVisible = message.ViewName == "UserControl2";
}
private bool isVisible;
public bool IsVisible
{
get { return isVisible; }
set
{
if(isVisible != value)
{
isVisible = value;
RaisePropertyChanged();
}
}
}
}
You inject the same IMessanger service into your ViewModel you use to Bind your UserControl2 and fire the message via
var message = new SelectedViewMessage {
ViewName = "UserControl2";
};
this.messangerService.Send<SelectedViewMessage>(message);
This code can be placed inside a ViewSelectedCommand or something similar, and you can use Blend Interactivity Triggers/Actions to bind this to certain events on the View/UserControl
This can be achieved by adding event onPropertyChange whenever user clicks on the tab and add that property in xaml under Visibility tag. Also look at Handling UI Control to understand that mapping in xaml and ti understand event handling from Here
Hope it helps.
I have mainPage.xaml and userControl.xaml.I called userControl in mainPage. mainPage has a Grid named "grd" and userControl has a button named "btn". Now when I will click on button then click event of userControl will be raised. In this event, I want to hide the Grid(that in mainPage.xaml). How can I access mainPage controls in userControls ?
For windows Phone 8 try this:
(((Application.Current as App).RootVisual as PhoneApplicationFrame).Content as Page)
You can access currently displayed Page using this code :
var mainPage = (PhoneApplicationPage)((App)Application.Current).RootFrame.Content;
Check out my answer, in that OP wanted to set visibility of appbar, my answer will work for Grid also.
how to programatically open and close bottomappbar using a eventhandler that exist in a usercontrol back code?
If you are using MVVM (as you stated in your comment to #har07's answer) you should not hide the grid in the main page using an event handler in your user control page. Instead you should bind a command to the button in the control page. This command should change the view model of the main page and this change should be notified by that view model to the main page.
In the next example I use MVVM Light but other MVVM libraries probably work almost the same.
Add a property to the view model of your main page:
public class MainViewModel : BaseViewModel
{
…your code here
private bool _isValid;
public bool IsValid
{
get
{
return _isValid;
}
set
{
_isValid = value;
RaisePropertyChange("IsValid");
}
}
}
In the main page bind Visibility to IsValid.
<Grid Visibility="{Binding IsValid, Converter={StaticResource converter}}">
…content here
</Grid>
Now, the grid is visible if IsValid is true.
Add a command to the view model of the user control:
public class UserControlViewModel : BaseViewModel
{
…your code here
public RelayCommand InvalidateGridCommand { get; private set; }
public UserControlViewModel()
{
InvalidateGridCommand = new RelayCommand( () => InvalidateGrid() );
}
private void InvalidateGrid()
{
var mainvm = SimpleIoc.Default.GetInstance(MainViewModel);
mainvm.IsValid = false;
}
}
In the user control page bind the Button to the Command:
<Button Command="{Binding InvalidateGridCommand}">
Invalidate
</Button>
Now, clicking the button will set IsValid on the MainViewModel to false, which will, in turn, hide the Grid.
I came here looking for an answer for this question and after some tries I could access the main page of my Windows Phone 8.1 app using:
var mainPage = (MainPage)(Window.Current.Content as Frame).Content.
To access the controls declared in the MainPage, you need also to give them a x:Name and change their x:FieldModifier to "Internal" or "Public".
I'm using an asp.net user-control in two different aspx forms. How can I customize the events handling of the user-control depending on the calling form ?
void ComboboxCountry_SelectedIndexChanged(object sender, RadComboBoxSelectedIndexChangedEventArgs e)
{
if it is form1 that called the User-control => do process 1
if it is form2 that called the User-control => do process 2
}
Thanks.
Despite the fact if this is a good design you are trying to implement: you could add a property to your control like
public BehaviourEnum Behaviour { get; set; } // You need to implement the enum
Then you could
void ComboboxCountry_SelectedIndexChanged(object sender, RadComboBoxSelectedIndexChangedEventArgs e)
{
if (Behaviour == BehaviourEnum.Behave1) // etc.
}
The pages implementing your control would need to set the Behaviour-Property accordingly.
Edit: If your control needs to interact with the parent page, I would introduce an interface on the parents page. Then you could design something like this:
// The page containing this control needs to implement IMasterpage
public IMasterpage Masterpage { get; set; }
void ComboboxCountry_SelectedIndexChanged(object sender, RadComboBoxSelectedIndexChangedEventArgs e)
{
// Propagate the behavour to your parent page
Masterpage.CallwatheverMethodInYourInterface();
}
The goal is to propagate behavour which depends on the parent page into the parent page itself. That way you can keep your control slim and independent.
I have a user control on a page. The user control has a public property on it that I need to set after a button click. How do you do this?
It appears that the control is rendered before the button click event fires, so setting the property has no effect.
Page:
<%# Register src="Email.ascx" tagname="Email" tagprefix="uc2" %>
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
EmailList.IsEditable = false;
}
protected void btn_Click(object sender, EventArgs e)
{
EmailList.IsEditable = true;
}
User Control:
public bool IsEditable { get; set; }
The public property gets set correctly when I set it in the page load event, but not on the button click.
The button is used to change the form from read-only to edit mode. Is there a way to set a public property in the button click event? If so, how?
The property is getting set just fine. The problem is where in your usercontrol you set it's controls to readonly/enabled.
If you want to be able to affect how the usercontrol gets rendered, you must do the logic where you're setting the readonly/enabled properties of the subcontrols in the Page_PreRender event of the usercontrol. This event is executed after the buttonclick events.
A must read on msdn: the page lifecycle. You'll notice the control events get processed after Page_Load and before Page_LoadComplete.
I have an asp.net page with many dozens of controls representing multiple database entities. I would like to track when any of the data for these entities is changed.
If I add a page member such as
public Page1 : System.Web.UI.Page
{
protected bool Entity1HasChanged { get;set; }
protected void RegisterChange(object sender, EventArgs e)
{
Entity1HasChanged = true;
}
}
Then for each control OnTextChanged event or equivalent I call a method that sets this boolean to true.
I would then like to run a method AFTER all control events have completed which does some database updates. What page event can I hook into to do this? Reading the page on the LoadComplete event it only states that all load events will have completed.
Does anyone know how I should achieve this? Am I doing this completely the wrong way?
Thanks,
Ian
Look at INotifyProperyChanged, INotifyPropertyChanging and INotifyCollectionChanged as your starting point.
Try OnPreRender.
ASP.NET Page Life Cycle Overview
This will also still allow you to modify the page output once you've completed the database operations (e.g. if you want to show a status box to say that the operations completed).
This is a really good question. I messed around with something quick that I think will work. You could create your won TextBox that inherits from TextBox:
namespace ServerControl1
{
[DefaultProperty("Text")]
[ToolboxData("<{0}:ServerControl1 runat=server></{0}:ServerControl1>")]
public class TextBoxWithChange : TextBox
{
[Bindable(true)]
[Category("Appearance")]
[DefaultValue("")]
[Localizable(true)]
public bool HasEntityChanged
{
get
{
bool hasEntityChanged = (bool) ViewState["HasEntityChanged"];
return hasEntityChanged;
}
}
protected override void RenderContents(HtmlTextWriter output)
{
output.Write(Text);
}
}
}
Then you could write a little jQuery script to change that attribute when the client side OnTextChanged event fires. On submit of the form you then could query that HasEntityChanged attribute for any of these TextBoxes.
For this example I put the server control in it's own Library and registered it like this:
<%# Register TagPrefix="MyCompanyName" Namespace="ServerControl1" Assembly="ServerControl1" %>
Then you can declare it on your page like this:
<MyCompanyName:TextBoxWithChange ID="ChangerTextBox" runat="server" HasEntityChanged="false"></MyCompanyName:TextBoxWithChange>