Actually i am trying to do a Wizard control. In which i have load 3 pages dynamically when click the next button. When i click the next button i need to store the page details so i have created a dictionary to store the usercontrol. Is there any other suggestions to store the previous page details.
There are many ways to achieve your requirements. This is what I would do, which I think is very inline with the MVVM design pattern.
Define a ViewModel class that contains all the variables that you want to collect (regardless of the partition to pages.
Add a public property named 'currentPage'.
Define the frame of the wizard. Probably a <Window> element, with a StackPanel. The Window would have a title at the top, and an area at the bottom for the 'prev' and 'next' buttons (and 'finish' if you want to).
In the main area of the StackPanel put a and bind its DataContext to the ViewModel
In the ViewModel create a Next and Pref commands (use Prism DelegateCommand, or implement your own lightweight version that derives from ICommand.
6/ Also, bind the 'Finish' button to a command, with the appropriate CanExecute logic (have you collected enough data?).
The Next and Prev 'CanExectue' logic would look at currentPage. e.g. the Prev command CanExecute will return false when currentPage is 0.
You'll have 3 different data templates, one for each page. Each data templates will present different subset of properties you want to collect at that page. Bind the UI controls to properties at the ViewModel, and have the binding mode two way.
Derive your ViewModel from INotifyPropertyChanged, and have all the setters to fire the appropriate notification. It is required for at least the currentPage property, but for the completion of the solution do it for all properties.
In the Next and Prev command Execute method will modify the currentPage property (the Setter should fire notification). The view will update automatically.
For the main area ItemControl, implement a WizardTemplateSelector derived from DataTemplateSelector. Define it as a resource, and assign the ItemControl.ContentTemplateSelector using {StaticResource} binding.
If you want to, you can also have a List control at the left side of the Window, with the Selected Item Index bound to the current page.
EDIT (Explainer): The basic idea is to have a single ViewModel, which can be Viewed in several different Data Template, depends on the current page.
Related
I have a WPF, MVVM program whose MainWindow is separated into a ListBox sidebar and a main part with a ContentControl. I want to create a functionality that will populate the ListBox with a button for each view that I have in my project and set its command such that clicking it will set the content of the ContentControl to the associated view automatically, i.e. so that I don't have to manually enter code when adding a new view. Something like iterate through all view files or something like that.
EDIT:
Perhaps I'm AGAIN not clear enough.
What I have and can do - type like a monkey "new Button, yadda yadda" every time I add a new view to my project.
What I want - write a piece of black magic that goes something like "There are 6 views in this project, I'll just make 6 buttons each such that, when clicked, will navigate to the appropriate view, without the guy who wrote me having to write any additional line of code any time a new view is added".
How can I achieve that and is it such a good idea, to begin with?
For instructional purposes, I'll be calling your "view" class View.
Create some sort of collection object (List<View>, ObservableCollection<View>, etc.) to store all of the Views.
Assign this collection to a dependency property. I'll call it Views.
Declare a dependency property for the selected/active view. I'll call it SelectedView.
Bind ListBox.ItemsSource to Views.
Bind ListBox.SelectedItem to View.
Bind ContentControl.Content to View as well.
With the above setup, the ContentControl will display whatever View is selected in the ListBox.
Mvvm, Wpf, VS2015
Hi All! I have googled this till my fingers bleed! But just hacks and work-arounds, or partial use of code behind.
My Wpf-Mvvm app uses Speech Synthesis.
Each button, (and in the next iteration, buttons using the selectedItem Index of Lists or ComboBoxes, to select the content(text)to be synthesized) specifies different content to be synthesized.
Sticking with Mvvm principles, in my viewModel, I need to capture which button, based on the List or ComboBoxes' SelectedItem/Value that is bound to the Parameter Command.
Why? So I can have the app synthesize the content(text/words)the user selects to hear. If not, I have to make separate commands and speech synthesizer methods for each.
There must be a simple clear-cut way. What am I missing here?
I thought of updating the Model's properties to reflect user's selection and use User Settings to persist,but have not tried yet.
Otherwise the Model's properties are accessible so far as encapsulation-wise to the ViewModel, but the property values from the Model still are not visible in viewModel.
I need the command bound control's ID/Name to route the content to be synthesized based on the model's class properties. But when I instantiate the model from the viewModel,
the model's properties are not there. I presume instantiating the Model class object from the viewModel, is in a different memory location, than the Model.
So I will try using User Setting's persistence for these properties, if no one else has a better way.
There has to be a clear solution to this, I hope :)
I know the View and ViewModel are supposed to not need to know what the other is doing. In this case though, I clearly need the List or ComboBoxes' Id or Name and their SelectedItem index.
I also need the button's Id or Name, because I have several groupings of content to choose from, and several buttons starting the synthesizing method.
Example: If the text content of an announcement to be synthesized, held in separate XML(SSML) files with identifier key values of 941, 23, 508, etc.,
I need to know which the User Selected to hear.
I imagine simply capturing in the viewModel, the Data-bound List/ComboBoxes' Selected ID index would suffice.
Thank you so very much for your help.
-Flazz
My question is as follows: my app needs to show a "Hamburger" menu in the left side, while the content right of it changes depending on the context. My initial idea was to implement it with Frames inside different Pages. I learned that the Frame itself is a reference to rootFrame so there's really no need for nested Frames to get navigation going.
However, to get the Hamburger menu on all Pages I would need to include them somehow. Is there a possibility to avoid duplicating the XAML code in every Page?
Looking into this I found UserControl. The docs are a bit hard to understand for me. Say I implemented a UserControl in XAML and named a Button in it via x:Name="HamburgerButton". Then, in myMainPage` I put something like this:
<Grid x:Name="MyGrid">
<controls:MyControl />
</Grid>
The Button in the UserControl XAML has a Click event in the code behind. How do I extend / customize the implementation of it in the MainPage that uses it? I guess I don't understand the relationships between them. Also the ContentPresenter is over my head at this moment.
You don't need the ContentPresenter. That's for when you create your own templates. Your MainView should contain your Menu buttons and a ContentControl. When a user clicks one of the buttons, you exchange the Content property of the ContentControl: For each menu item you can create an extra UserControl, one of which is always set to the ContentControl. For example, when the user clicks "Menu X" then you set the Content property of your ContentControl to UserControlX that contains all the context-related things. When the user clicks "Button Y" ... you get the idea.
You can do all this from the code-behind file of your main view. In the long run, you'll probably want to look into the MVVM pattern and bind your ContentPresenter to a property of your MainView's view model - and your buttons potentially to ICommands. But it will also work via the code-behind method.
I have created an UserControl that encapsulate two UserControl.
The first one is a "model" that can be changed by the User. It represents a ObservableCollection of TextBox. Each one of them is filled by the User.
My second UserControl will be a List of UserControl.
Each sub UserControl will be a list of textbox.
I want to be able to create my second UserControl by using the information of the first UserControl ==> Text in each Textbox used in tooltip of textbox.
So what I want is when the user add a field in the first usercontrol to be able to add the same field in each item of my second UserControl.
The black rectangle represents my model and the red rectangle represents my second usercontrol so the use of my model to create a UserControl.
Each UserControl owns his ViewModel.
Thanks in advance.
Hi please try the next architecture:
First User Control observable collection. The ObservableCollection supports event which will be raised when item will be added/deleted/etc. Submit on this event in your first user control view model.
Second User control let its view model be composed of ObservableCollections.
Share the EventAggregator (link here) between view models of your controls. First user control view model will be publisher and the second will be subscriber.
Each time when the observable collection of the first user control view model will be changed, publish the aggregator event to inform about the fact that this collection was changed.
Second user control will get the event and perform action (add/delete) on all its collection.
update
You can manage the sharing mechanism so that the EventAggregator will be the same reference, but the published object will have a key which represents a particular tab (for example the hash code of the tab), thus each subscriber will know if it have to response or not.
That's all. Try to perform that, I'll be glad to help if you will problems with the code.
Regards.
Ok, this is going to be a 1000ft long question, but there's a lot to cover so here goes:
I am creating a paged items control, the purpose of which is to display very large collections in a paged format. I've created a repository on GitHub which can be found here. I have removed any styling for simplicity.
Upon starting the application, it looks like this:
This is pretty straightforward really, there's navigation buttons, an items per page selector but that isn't really important. The problem here is when you click the button "Open New Window".
This will open a new MainWindow, but on the first window, the collection disappears, as shown below:
The image above shows the old window in front, as you can see, there is no list of content as there is on the new window.
So, after smashing my head against a wall for a couple of hours, I am in need of assistance. I'll provide an overview of how the project is structured.
AnagramPagedItemsControl
The control being used for displaying the content is a custom control called AnagramPagedItemsControl, it is responsible for handling navigation between pages. I think the key property here is the PagedCollection.
The PagedCollection dependency property holds the collection which is bound to the Models property in the TestItemsViewModel.
TestItemsViewModel
This is the DataContext of the MainWindow, each window instance should create it's own view model. The CreateTestItems() method is responsible for creating the list of test items.
LazyPagedCollection
The purpose of this collection is to encapsulate the logic of a paged observable collection, it only loads pages when they are needed, hence the laziness.
It exposes methods like NextPage which are called in the AnagramPagedItemsControl when the user clicks on the various navigation buttons. The view model can also call navigation on the LazyPagedCollection, this allows the view model to call navigation without having to go through the view to do it.
TL;DR
When I create a new Window, the content of the previous window disappears. The problem is almost certainly with the control however I am stuck as to how to fix the problem.
This is quite a large problem to look at so I'd be very grateful for anyone who can look into it. Again, the source code is here, please feel free to suggest alternatives or pick out anything that I may have overlooked.
Had some time to spare, so:
The problem is the setter for the CollectionView property in the style for AnagramPagedItemsControl in generic.xaml.
This does not instantiate a new ListBox every time the style is applied; it will just create the one ListBox, the first time the style is created, and use that value over, and over again. So in effect, every instance of MainWindow shares the same ListBox.
You can see this by setting the Tag property of PART_CollectionView to (for instance) "1" in SetupBindings(ItemsControl PART_CollectionView). When you open a new window, you'll see that PART_CollectionView.Tag contains the same value you previously assigned.