I'm new in WPF and I need to group many components in one element and make and add new instance of that element in window for each student in database like 2 textblock plus 1 textbox for each student, how can i do something like that?
This is where WPF really shines - you can use an ItemTemplate or a DataTemplate to style the UI with the underlying data objects knowing absolutely nothing about how they are being presented.
Check out Data Templating for an introduction. Effectively an ItemTemplate is a template (definition) of how each item should be rendered. A DataTemplate goes a step further and gives you the ability to select which template to use based on the data item being bound to, so you can have a list containing different types of objects yet still show them all in the same list/repeater control on the screen.
Related
I currently have a class object that is bound to a listboxitem. Before I used to get the other objects inside the ListBoxItem by clicking a button and accessing its parent, but now I need to gather the objects without clicking the buttons or labels, just by its class.
I've tried to gather the ListBoxItem with its index and its class binding, but both of them is giving me a null value:
ObservableCollection<ClassBinding> classList = new ObservableCollection<ClassBinding>();
... adding items here to the collection;
listBox.ItemsSource = classList;
ListBoxItem lbi = (ListBoxItem)listBox.ItemContainerGenerator.ContainerFromIndex(index);
Is there another way to access the listboxitem to later gather the other objects by using the function FindName(...)?
Debug:
TextBlock delay = lbi.FindName("lblDelay") as TextBlock;
Error:
Output: Exception thrown: 'System.InvalidOperationException' in WindowsBase.dll
A ListBox is virtualized by default, see Displaying large data sets.
Typically, you do not have to display all the items at the same time; instead you display a subset, and the user scrolls through the list. In this case, it makes sense to use UI virtualization, which means the item container generation and associated layout computation for an item is deferred until the item is visible.
In other words, you get null, because the ListBoxItem in question is not yet visible and realized. The only reliable way to get around this is to disable virtualization to force instantiation of all items. Although you can then access each item, this can result in bad performance for large collections, since all items are loaded when the ListBox is loaded and all items are held in memory which increases the memory footprint.
<ListBox x:Name="listBox" VirtualizingStackPanel.IsVirtualizing="False">
Accessing child controls, e.g. in data templates by name with FindName(...) does not work in ItemsControls like ListBox. You will have to walk the visual tree to get the controls, see:
How can I find WPF controls by name or type?.
In general, it is not a good idea to deal with controls in an items control directly. It is much easier to use data-binding, where you will not have any issues with containers and virtualization as you do not access them directly. Furthermore, your code will be simplified and you do not need to assume a visual structure.
For more information and examples on this topic, you can refer to:
How to: Bind to a Collection and Display Information Based on Selection
Data binding overview (WPF .NET)
Data Templating Overview
WPF Databinding With A Collection Object
In order to find another solution/idea for this I came up with the INotifyPropertyChanged that can be added inside the classes, so there's no need to remove the ItemsSource from the list box, just hook the items source at the load of the program and then you can change the data inside the collection.
I used the code from here: INotifyPropertyChanged and ObservableCollection WPF
I didn't need to access the text blocks, just hooked some bindings to the objects and was able to do UI changes from just changing the values of the classes.
I'm creating a WPF program that consumes rest api data. I want to implement lazyloading and infinite scroll on the data and programmatically create and add either custom data templates or listitems very similar to this design
I'm just confused as to which approach to take and what benefits/costs each provides
Easy choices:
Everyone uses MVVM so use MVVM.
Data Templating is a fundamental of wpf and building UI in code is not recommended - so use data templating.
You can dynamically add templates to resources by building xaml as strings. This is the MS recommended way to build any dynamic UI. Those strings can come from flat files, a database directly or a web service and you can build them by manipulating txt files or serialising controls.
A huge plus of this is you have the markup "right there". So when things go pear shaped you can paste into an experimental solution and see the errors light up in the xaml or see what the user is seeing.
If datatype associated templating doesn't suit for some reason then you could write a datatemplateselector and put your logic in there.
I'm not sure how you expect that to scroll exactly but I'd go with a listbox, some datatemplates associated with a type per view. Assuming the items can have different views - you just seem to have that "gilded" button or tag as an option.
Load your data into viewmodels with one per row.
.Add to an Observablecollection which is a public property in a viewmodel.
Bind that to the itemssource of a listbox.
They are then templated into UI.
A listbox has a scroller built in but you could re-template if you wanted to scroll using some other approach.
A StackPanel is a Panel that arranges child elements into a single line that can be oriented either horizontally or vertically.
A ListView is an ItemsControl that you can bind to an IEnumerable of objects and is used to present a collection of items.
What you should do is to create an ItemsControl with an ItemTemplate that corresponds to a scrollable item in the list. There is a basic example available here and you will find a lot more examples online.
I'm pretty new to WPF/XAML in C#, I saw some simple tutorials and stuff but, today I'm confused, never used to make UI there.
I need to output multiple forms which instance would look something like that:
(NB: I constructed it just in WYSIWG way, so XAML markup is total mess, it for screenshot. I cant even add table directly in grid, oh)
I got data like this for each month in schoolyear, so, depends on what class is choosen I want it to output like that (scheme)
(NB: instead of each CustomWindowInstance there I need my form from 1 st screenshot)
So, whats is best and simplies approach for that?
EDIT 1: I'll name XAML from the first screenshot, which represents controls you want to display multiple times, XAML 1, and another one, where you want to do it, XAML 2.
--
Almost ORIGINAL:
Create a separate User Control and move the content of Window tag from XAML 1 into it. Then you'll be able to show it as many times as you want by placing <yourUserControlNamespace:YourUserControlClass /> in XAML 2.
For an ability of communication with this control in XAML like <yourUserControlNamespace:YourUserControlClass Parameter="SomethingHere" /> you should implement a dependency property with name ParameterProperty (desired name of property in XAML + "Property") in YourUserControlClass.xaml.cs.
--
EDIT 2: One may also create a DataTemplate with parameter DataType={x:Type yourVMNamespace:YourVMClass} for the XAML 1's ViewModel (not View) in XAML 2's or the whole application's Resources. In that case the ViewModel class you are binding to will be represented by the DataTemplate's content itself. Later you can write <yourVMNamespace:YourVMClass /> as in the first solution.
This approach allows displaying rich representation of any items themselves, for example, in controls derived from ItemsControl, such as ListBox, all you've got to do is to bind ListBox's ItemsSource property to a collection of YourVMClass instances (or specify them in XAML by hand).
More precisely, in this case I won't call YourVMClass a ViewModel.
I have a Grid bound to an ObservableCollection. I want to have an extra item in the grid such that it displays as just another tile but is actually, e.g., a button. Microsoft's Finance app demonstrates the effect I want perfectly (screenshot below). The goal is to have a final tile that is not itself a member of the collection, but sits in the grid like any other item.
The top answer to a similar question mentions the CompositeCollection, but CompositeCollection does not seem to be available for Win8 apps.
You could always add and extra item at the end of the ObservableCollection, you're binding to.
You could handle this exception in the view model: add it during loading, properly handle adding and removing the rest of the items if you support that in your app. (That's the approach we took in one of our projects.)
Or you could derive your own class from ObservableCollection to handle all that and reuse it.
To have the extra item display differently from the others, you can use a DataTemplateSelector and select the right template based on the type name or some other property that differentiates the extra item from the rest.
Here's sample project which shows standard items template (GridView, with ListView for snapped view) that adds a "+" content item to the ItemsSource, which is used for the "Add New Item" action in the app.
"Add New Item" item in GridView / ListView
I have some problems trying to update components of surface elements. I dont know if my approach to the problem is wrong, since I'm new to the topic.
My point is represented by the following diagram
According to the option that is selected in the menu, load different user controls as only child of StackPanel but i'm habing problems for update the Listview from loaded user controls, example: when I save a new item I need to recharge the list of items in the ListView
MVVM would be a good pattern here. If you have a problem passing data between controls - why not introduce them on top of unified data layer? Consider this:
Three radio buttons in your Menu, each one's IsChecked property bound to Visibility property of your respective UserControl.
StackPanel holding all three UserControls
ListView bound to ViewModel's List<Item>
Each of your UserControls bound to ListView.SelectedItem: one of them using TextBlock for read-only, one using TextBox for editing. Third one would create new item in your List<Item>. You would have to create ItemTemplate for each or create one UserControl (since they look very much alike) and use DataTemplateSelector.
If you're not familiar with MVVM here is a good start. You can also use one of the existing frameworks like MVVM Light
You can create an event on your child
public delegate void HandleNAMEOFYOURHANDLEEVENT();
on your child class
public event HandleNAMEOFYOURHANDLEEVENT yourInstance;
to use it on your child class
if (!ReferenceEquals(yourInstance, null))
{
yourInstance();
}
and you declare it on your parent like other event.