I started a project using TemplateStudio for WinUI (C#) 5.2. It uses the CommunityToolkit ListDetailsView Control for a "List Details" page.
What is the best way to load additional data when a user selects something from the list of results? I thought I would add two more properties to my ViewModel (one to handle the data, one to show a busy animation while the data is loading, both using ObservableObjects SetProperty), when the selected gets changed I fetch the data async for the selected item and update the ViewModel properties accordingly.
I can't seem to find a way how to access this data from the DetailsViewControl, and I'm not sure I do it the correct way anyway.
If I add a property to my model and change the value on changing the selected the data gets added, but the UI doesn't update itself (I tried _selected and Selected). Only when selecting another item from the results and going back to the previous shows the value.
What would be the best/correct way to lazy load additional data with this control? There would be about 4-5 parallel requests going on in the first release.
Later on I need a few buttons in the DetailsViewControl as well, where and how am I supposed to handle the commands?
Or am I better of not using this control and do it manually?
Related
I have a rather simple sounding requirement. Currently, we have a Combobox which is rather inefficient because it attempts to load all the data from DB when the box is clicked. This Combobox is not typable and all I have to basically do is ensure that the data is loaded in chunks at the appropriate times i.e. when the user is at or near the end of the Combobox.
My initial thought was that there should be an event which I could bind to when the user scrolls towards the end of the Combobox, but no such event exists based on what I could see in event list.
My alternative solution is to bind on mouse wheel down event and have a method which constantly polls whether the last item is visible (although I'm not sure such property exists) and if it is, load more data.
My last hunch is that there should be some sort of asynchronous stream data approach to this problem which would just basically load rows without locking up the UI continuous instead of one big chunk.
Can anyone suggest anything and maybe show a quick demonstration?
Kind regards,
Vocal.
I am struggling some time with checkbox control in WPF. What I am trying is to to make some kind of filter.
1. So first I need to fill the checkbox control with the database items
2. Second I need to check if anything is checked
3. Third if anything is checked I want to take those values and use them to search through the database
4. Should I use only checkbox control for this or should I put it in some container or a listBox?
I have find many topics here that are mentioning this stuff, but I couldn't manage to find the complete answer, only lot of parts that are not compatible with each other. I would really appreciate if someone explain to me how checkbox in WPF works.
If you have multiple values and you want to display multiple CheckBoxes, one for each of them, then you will need to use a ListBox and have the TemplateItem a CheckBox. This way your collection of items is bound to the ListBox, and for each item in the ListBox a CheckBox is shown.
So to get each of the values after there is an additional step if your doing MVVM and don't want to touch the UI. What you do is create a wrapper class that sits around your class and has a extra property for the IsChecked data. This way you can get the checked state without touching the UI.
I have an example of this on my blog:
Checked ListBox in WPF
To check which items are checked you just need a simple LINQ query. So if you use the example there from my blog then you should be able to do something like this:
var checkedCustomers = Customers.Where(w=>w.IsChecked).ToList();
EDIT: I needed to skip control creation during post back -- see my answer below.
I'm working on a very basic front end to a simple tool and I wanted to present some data in a much more sorted and useful way, instead of making one huge wall of text. I found this tutorial on building a simple tabbed interface using MultiView, but have run into a bizarre problem. I can't use Ajax tabs because of legal hissy fits over 3rd party software.
My webpage is a basic ASP.NET page with a user control plopped in the middle of it. In this control's ascx file, I defined the Menu (empty) and the MultiView (also empty) so that I can dynamically populate the tabs with content driven from an external file.
When the default page's OnInitComplete function is called, I call through to the user control to load the data file, then build out the tabs and the view content based on the loaded data. I tried doing this from PageLoad, PreInit, and CreateChildControls, but I kept getting an errors saying that I was setting the the MultiView's active view index at an invalid time (and also that there were 0 views despite the fact I just added a bunch of them):
ActiveViewIndex is being set to '0'. It must be smaller than the
current number of View controls '0'. For dynamically added views, make
sure they are added before or in Page_PreInit event.
But OnInitComplete appears to work just fine, so I went with that.
I iterate over the loaded data (multiple lists of strings), and for each list, I add a MenuItem with the list's title to the Menu and a View to the MultiView. The View is populated with a table->row->cell as in the above tutorial. In the cell, I add the list title and a CheckBoxList data bound to the list of strings.
So far so good, but when I click on a tab (or one of the checkboxes, etc) and there is a postback or something like that (the screen flashes as the site redraws itself), there is now a duplicate set of MenuItems immediately after the original. Each time I click on a tab or checkbox, another set of menu items are added.
I clear the MenuItem's Items list prior to building the controls and I verify that the controls hierarchy is structurally as expected after the control construction. Yet when one of my callbacks is called, my MenuItem list magically has some items added to it. None of my other controls appear affected at all. As a hack, I can remove the duplicates manually in my menu's OnMenuItemClick event, but I'd have to do the same in any of the callbacks I receive. Obviously I'd rather prevent this from happening. This has me stumped and I haven't been able to find anything online about it. Why would one set of controls have some content duplicated, yet every other control maintain its state correctly? My code is really simple so there isn't a way to add additional menu items without also adding the views. Anyway, there are a correct number of items prior to clicking on the tab/checkbox, an additional set immediately following in the callback.
This is my first time using ASP.NET, so I'm learning as I go. :) Thanks!
My problem was that I was not testing for postback before creating the controls. The code below is working for me.
In my user control's code behind:
protected void OnInitComplete( EventArgs e )
{
if( !Page.IsPostBack )
{
CreateMyControls();
}
}
I should start by saying I'm relatively new to the MVVM pattern. Having said that, I've got two tabs I'm trying to load with large data sets. I would like for the first tab to load when the page is loaded, but when you click the other tab for the first to be unloaded and the second to be loaded (aka Lazy Loaded). Any ideas as to how to do that?
It's important to keep the UI responsive to the user and loading large amounts of data can have a negative effect on that experience. That's why in situations like yours I have the view-model call a method that uses a BackgroundWorker(s) to load the data. The earlier you do this in the app's lifecycle, the better your user's experience.
So, like mathieu suggested, bind the control's property to your view-model and have your view-model load the data in a non-blocking fashion.
You can bind the SelectedValue property of the TabControl to a property of your viewmodel.
This way you can unload/load the correct data when the property value changes.
I have a MVVM (Prism) application that I need to implement a master details screen wheer the master is a listview and the details is displayed next to it. Read-only seems easy enough (haven't done it yet but I've got my head around WPF binding) but edit/add confuses me.
How to I make it so the master is not updated until the details is saved?
How do I make it so you can't change the master's current selection while in edit/add mode?
I've been googling a plenty but have not found any meaty examples of this.
Thanks.
PS: This view is a child view on a larger screen. This is why I want both master and detail together.
You certainly can do this, though in my opinion such a UI design fails to harness the full power of WPF. Old WinForms UIs usually didn't update most of the application until data was saved to SQL Server (or wherever) because they didn't have real business objects and a powerful binding system like WPF. Trying to copy WinForms limitations within WPF seems like a step backward to me. Why not show the latest data everywhere it is visible in the UI, including in the master view? Also, why not allow the user to edit multiple items before saving, for example marking any edited but unsaved item with an animated marker in the master view? Combine these with a generalized undo and you have a better design and more intuitive for the user.
However if your business requirements make it absolutely necessary, here is how to do it:
Preventing changes to data from being visible outside the detail until it is saved
Upon entry into your "edit/add mode", make a copy of the data objects and set your detail view's DataContext to the copy instead of the live object. When the data is "saved", copy the data from the shadow copy back into the live object and set your detail view's DataContext back where it should be.
Preventing the master's current selection from changing while in edit/add mode
Two possibilities:
During edit/add mode, change the master view to disallow mouse hit testing or keyboard focus
When edit/add mode begins, capture the "current selection" then add an event handler that watches for "current selection" changes and immediately changes the selection back to what it was. When edit/add mode ends, remove the handler. This handler can be conveniently coded using a lambda expression and using a closure on a local variable to store the current selection.
Thanks for the answer. Now I've re-read my message, I see it is rather vague. I have a screen that edits an object which contains multiple lists of other child objects. I've implemented these as different tabs in a tab control. One of these tabs edits the comments, so I wanted to display a list of comments with an edit panel for the current selection next to the list. The user could then use add, edit or delete buttons to update the list. I wanted to do this in a pure(ish) MVVM way.
I came up with the following design which seems to work with minimal hacks.
The View includes a list of the child objects simply as a ListView bound to an observable collection within the ViewModel. I included a child object buffer – this is used to buffer changes until they are ready to be saved back to the list (or thrown away).
The View also includes an edit panel bound to the buffer object in the ViewModel. The buffer is updated whenever the list view’s current selection changes using a deep copy. I tried using data binding on the Selecteditem property but the set was never called, so a small code-behind method was added to force the property to be updated when the selection was changed.
The list view and edit view are mutually exclusive. In theory you could hide the disabled one, perhaps using a flip screen. As a general pattern, it is better for my app to have both visible at the same time as the edit panel may show extra information not shown in the list view. The choice as to which panel is enabled is controlled by binding IsEnabled to a ViewModel property like IsEditCommentMode.
Commands to manage the list have to be added, these are New, Editand Delete. Note that Add and Edit will set set up the buffer then set IsEditCommentMode to true. These list management commands are only available when IsEditCommentMode is false.
The edit panel implements Save and Cancel commands, they are only be enabled when IsEditCommentMode is true. When Save is executed, it should copy from the buffer to the list (either add or update) and fire the change notification. Finally, it should set IsEditCommentMode to false.
This all works well and does not seem to violate any MVVM tenents (in my humble but often flawed opinion).