I want to pass navigationservice to my user control.
At my application side
<myControl:Test NavigationService="{Binding NavigationService}"/>/>
at my Usercontrol CS side
public NavigationService NavigationService { get; set; }
but it dosent seems to work,application crashes as soon as it loads.
That's really harsh... Alright, You haven't mentioned this, but I suppose, that you try to solve the problem of navigating from UserControl to other page/uc(is it true?).
A couple of edits:
First, You don't need an object of class to use a
NavigationSevice.
Second, the NavigationService is most usually used with pages.
If you really do want to use it with UserControl, you should transfer an instance of page to control. But, in my experience, usually, this is not required. I would rather recommend to do in this way:
In your UserControl you will most definitely have the controls with tap/click events. No need to describe their logic in user control class. When you add the user control to page, you should declare it there. Like:
someUserControl.buttonNavigate.MouseLeftButtonUp += new MouseButtonEventHandler(buttonNavigate_Click);
And then you can use navigation service.
NavigationService.Navigate(new Uri(...));
That's the easiest solution. Hope it helps.
There are another ones, but I hope this one will solve the problem.
Related
The NavigationService system that comes with MVVM Light seems to assume that I want to make the whole window navigate to another page, however, I would like to have a lateral bar from which I can select to which page to go, something like a hamburger menu in cellphone apps. That is, I only want to navigate using this frame that is inside a NavigationView.Content.
I could get it going by binding the content frame to the MainPageViewModel and navigate using it, but I would rather use the NavigationService provided by MVVM Light to learn it better.
Thanks for the help!
I could get it going by binding the content frame to the MainPageViewModel and navigate using it, but I would rather use the NavigationService provided by MVVM Light to learn it better.
You're on the right direction. Even if you use the NavigationService class provided by MVVMLight, you still need to provide your content frame instance for its CurrentFrame property. You could check its source code on GitHub.
For example,
var nav = ServiceLocator.Current.GetInstance<NavigationService>();
nav.CurrentFrame = YourframeControl;
Here, I wanted to provide an easy way to you. You could try to use the WindowsTemplateStudio to create your UWP project. You could choose 'Navigation Pane' project type and 'Mvvm Light' design pattern. Then, you would find that the 'WindowsTemplateStudio' has helped you do all relevant things. On the 'ShellPage.xaml', it has a NavigationView control for navigation. It also has implemented a NavigationServiceEx class for you.
In the ViewModelLocator.cs:
public NavigationServiceEx NavigationService => SimpleIoc.Default.GetInstance<NavigationServiceEx>();
In the 'ShellPage.xaml.cs':
ViewModel.Initialize(shellFrame, navigationView, KeyboardAccelerators);
This will do the same thing as my code above. Then, when you use the NavigationService to navigate to other page, it will use the 'shellFrame' control to navigate.
I have 2 problems:
"Which Button called this form?" (short version)
I can not touch the button or button's form
Why do I want this?
I have many forms and need to know how the user got there. If I could get the Form (not the button) it may also solve the problem.
Long version: I need to copy some properties of source form/button to the new one without do it manually and I intend to use it later on Exception reporting to catch more info
Initially, i tried to do a "newForm.Caller = this;" on each button but there are 200+ forms and lots of buttons on each.
All forms and it's buttons are custom controls so I can do things there.
Tried things
I tried to do things with StackFrames and reflection at form constructor but don't work (889310)
I found this 10401190 for JAVA but it can't help
I thought I could use the OnClick override to store the last button instance in a static place in buttons/forms class then get it in the form constructor but seems to be the worst solution. (Many things open forms and the culprit would be the last button pressed)
The problem get worse when other things open Forms and I lost the reference (DataGridVewButton, timers, linked label, ...)
EDIT1: (oɔɯǝɹ)
Another detail, forms can be called from external Plugins. So again I don't have acesses to the code to change it.
EDIT2: Example (Graham Bass,ShreyasKapur)
FormA has a ButtonA that when clicked shows FormB
FormA inherits FormBase
Button inherits ButtonBase
FormB inherits FormBase
I can NOT change FormA neither ButtonA codes, only FormBase and ButtonBase codes
Edit3: (Bradley Uffner)
ShowDialog() forms have the Owner property that solves part of the problem. Thanks Bradley, I forgot about that!
Unfortunately, all existing code uses the parameterless constructor.
"Displays this form as a modal dialog box with no owner window" (1)
I would think that you are trying to solve the wrong problem.
When your forms are this interconnected, you coupled them to tightly. By coupling them even more tightly by looking back to who called you, you are only making you problem worse. See also: the comefrom instruction.
I would suggest passing parameters between your forms to supply them the data they need. But keep the number of parameters to an absolute minimum, and don't try to use something like caller, that would be cheating.
Suppose, I have two XAML page: MainPage.xaml & Page1.xaml.
For navigating to Page1.xaml, I always use this code:
Page1 mynewPage = new Page1();
this.Content = mynewPage;
But I see people using other codes for navigating purpose. Am I doing this in an inefficient way? What's the most efficient way to do this?
use this.NavigationService.Navigate(new Uri("/Page1.xaml", UriKind.Relative));
In that case you have not control about, for instance going back,in your case have to create code to manage the navigation by yourself, and you might to need to store the information of each page at a time, that is automatic when you do it.
Apart there are transitions between pages that are great to show the user that the page is changing. Of course you can create your own transitions but at the end you are creating the navigation by yourself.
With navigation you can control the events of Navigating and navigated and use them to initialize the page, etc.
In windows phone 8, you should use "NavigationService". NavigationService contains methods, properties, and events to support navigation and implemented by Microsoft.
Your code just updates content. It doesnt keep navigation history. So, you cant use back button unless override. You cant pass parameter to another view or you cant know navigation sucessfully ended.
To sum up, navigation service offers all of these features and mores. For detail information , you can checkout in app navigation model from here: In-app navigation for Windows Phone 8
I need to build some kind of phone emulator to test our webservice and have a general idea how the flow will go.
Doesn't needs to be anything fancy.
Now I made a WPF form with a phone image in it. In the display of the phone I have placed a frame. That looks good so far :)
But what now? How can I fill the frame with say the startscreen? Do I need to create a usercontrol for each page I want to view or show? Or is there another approach?
And how about databinding? I want to use MVVM, so I need to create a viewmodel for each usercontrol like we do normally? Or a viewmodel for each page?
I just discovered the WPF Frame Control and it seems there's not so much info on the net to find, or not what I want.
Thx for any pointers in the right direction.
Here is an image how it now looks:
For each view (screen) that the end user is going to see you will need to make a page that will hold all your logic and functions per page. All you do in Cycle through the pages in your own way.
FrameName.Navigate(PageName);
Remember to initialize the pages before you can use them. You can intialize them when you use the Navigate function like:
FrameName.Navigate(new PageName());
This works well for smaller projets, bigger projects you might want to use some clever way of initializing the pages because you navigate, like:
if(TimeToLoadPage == True)
{
PageName pagename = new PageName();
RunPageNavigation()
}
public Void RunPageNavigation()
{
FrameName.Navigate(pagename);
}
You can data bind the width and height of the page by inheriting from the Frame (Going through Ancestry route). You can do all the content based stuff in a page exactly the same as a window. You can't however control the page like a window.
Hope this helps a bit more.
I have a Form and a UserControl. The UserControl has a menu, and the form has a tabstrip (General, Food, Vitamins etc).
In the UserControl, I have the following code: (Form name is frmForm, the tab names in the form are tabGeneral,tabFood, tabVitamins)
frmForm fm=new frmForm();
fm.tabMain.Selected=tabVitamins;
I call these line from the UserControl to capture the tab to get selected on the form, but it does not select the vitamins tab.
Where am I going wrong? I have access specifier as Protected Internal for tabs in the form.
Please advice.
Thanks,
Karthick
When you write new frmForm(), you're creating a completely new instance of frmForm, which is then discarded.
To get the frmForm instance that holds your control, call the FindForm() method and cast to frmForm.
For example:
frmForm myForm = FindForm() as frmForm;
if(myForm != null)
myForm.tabMain.SelectedTab = myForm.tabVitamins;
If the control is on some other form, this code won't do anything.
By the way, Hungarian notation is frowned upon in .Net.
Your form should probably be named something like MainForm.
SLaks has correctly pointed out your fundamental error, and given you a valid example of a way, via a call to the method 'FindForm, to get the Form the UserControl is sited on.
It may be valuable to you to keep in mind that a UserControl (and all Controls) also has a 'Parent property, but, of course, a UserControl could be placed inside another Control on a Form (like your UserControl could be inside a Panel on the Form) : in that case the UserControl's Parent would be the control it's inside on the Form (like, a Panel), not the Form itself, but 'FindForm will do the right thing to get you the Form it's on.
However you are calling a Method every time you use 'FindForm, and "best practice" suggests that what you want to do is to "inject" a reference to the Form into the UserControl at run-time so that it can always access its Form property easily, without calling a 'Method.
In your example, on a practical level, this (calling the Method) may make almost no difference in performance, but, imho, as you get to a place with WinForms and .NET where you might have a UserControl that will need access to its Parent Form very frequently, this will pay off, and it's a better way to structure your code in the long run, for maintenance.
Wes showed you one way you can "embed" (inject) the UserControl's hosting Form : using an overloaded constructor for the UserControl. But that requires you to modify the Designer.cs file in standard WinForms, and I strongly advise you against that, even though it will work. Particularly if you are just "getting your feet on the ground" in .NET, I strongly advise you against modifying it, or anything having to do with the Form's constructor and its internal call to : InitializeComponent();
Also, as you progress with WinForms you are going to meet many situations where you are going to want instances of "objects" (a Control, a Form, an instance of a Class) to contain references to other instances of "objects.
If you can understand and use one simple use of "injection" here, you are going to make progress to make yourself ready to handle more complex .Net programming in the future.
Another way is to put a Public Property in the UserControl that can be set in code from the MainForm. In the UserControl something like :
private frmForm ParentForm;
public frmForm UCParentForm
{
set { ParentForm = value; }
}
So then in your main form's code, perhaps in the Load event like this :
private void frmForm_Load(object sender, EventArgs e)
{
TheUserControl.UCParentForm = this;
}
or when you need to, you set the UserControl's 'ParentForm property once. So you have eliminated using the method 'FindForm().
In this case, if you only want access to a specific control on the UserControl's Parent Form, like a TabControl, you might consider that you want to make the Property you set of type TabControl, rather than Form : the same coding technique shown above can be used in the UserControl :
private TabControl mainFormTabControl;
public TabControl MainFormTabControl
{
set { mainFormTabControl = value; }
}
imho, it is when you are creating UserControls dynamically at run-time, using an overloaded constructor, as Wes suggests, is the best strategy. And using overloaded constructors has many, many others uses in .NET that you'll get into.
good luck !
You should not be creating a new frmForm() inside the user control. You could pass a reference to the frmForm to the user control.
In your user control constructor try something like this.
private frmForm fm;
public YourUserControl(frmForm fm)
{
this.fm = fm;
}
Then you could use.
fm.tabMain.Selected=tabVitamins;
Does that help?