In-depth discussion on the ListView control of WPF, wpflistview
Next to the previous blog, I initially discussed the ListView control of WPF (involving templates and searching for child controls). We will continue to discuss the usage of ListView.
I. Sorting
The requirement is as follows: if we put the scores of students into the ListView, we can sort the scores in the single-host ListView header, and change the Xaml as follows:
<Window x: Class = "ContentDataTemplate. MainWindow" xmlns =" http://schemas.microsoft.com/winfx/2006/xaml /Presentation "xmlns: x =" http://schemas.microsoft.com/winfx/2006/xaml "Xmlns: c =" clr-namespace: System. collections; assembly = mscorlib "xmlns: local =" clr-namespace: ContentDataTemplate "Title =" MainWindow "Height =" 350 "Width =" 525 "> <Window. resources> <c: ArrayList x: Key = "stuList"> <local: student Id = "1" Name = "Xiao Ming" Grade = "Yan Yi" Professional = "Computer Technology" Score = "30" HasJob = "true"> </local: student> <local: student Id = "2" Name = "Xiao Li" Grade = "Freshman" Professional = "network engineering" Score = "80" HasJob = "true"> </local: student> <local: student Id = "3" Name = "Xiao Zhang" Grade = "Yan Yi" Professional = "Software Engineering" Score = "100" HasJob = "False"> </local: student> <local: student Id = "4" Name = "" Grade = "1" Professional = "Automated Control" Score = "70" HasJob = "true"> </local: student> <local: student Id = "5" Name = "" Grade =" 1" Professional = "Software Design" Score = "60" HasJob = "False"> </local: student> </c: ArrayList> <DataTemplate x: Key = "NameDt"> <TextBox x: name = "textboxName" Text = "{Binding Name}" GotFocus = "textboxName_GotFocus"> </TextBox> </DataTemplate> <DataTemplate x: key = "GradeDt"> <TextBox x: Name = "textboxGrade" Text = "{Binding Grade}"> </TextBox> </DataTemplate> <DataTemplate x: key = "ProfessionalDt"> <TextBox x: Name = "textboxProfessional" Text = "{Binding Professional}"> </TextBox> </DataTemplate> <DataTemplate x: key = "ScoreDt"> <TextBox Name = "textboxScore" Text = "{Binding Score}"> </TextBox> </DataTemplate> <DataTemplate x: key = "HasJobDt"> <CheckBox x: name = "CheckBocHasJob" IsChecked = "{Binding HasJob}" Checked = "CheckBocHasJob_Checked"> </CheckBox> </DataTemplate> </Window. resources> <Grid Margin = "5"> <ListView x: Name = "ListViewStudent" ItemsSource = "{StaticResource stuList}"> <ListView. view> <GridView> <GridViewColumn Header = "ID" DisplayMemberBinding = "{Binding Id}"> </GridViewColumn> <GridViewColumn Header = "name" CellTemplate = "{StaticResource NameDt }"> </GridViewColumn> <GridViewColumn Header = "" CellTemplate = "{StaticResource GradeDt}"> </GridViewColumn> <GridViewColumn Header = "professional" CellTemplate = "{StaticResource ProfessionalDt }"> </GridViewColumn> <GridViewColumn Header = "score" CellTemplate = "{StaticResource ScoreDt}"> </GridViewColumn> <GridViewColumn Header = "working" CellTemplate = "{StaticResource HasJobDt} "> </GridViewColumn> </GridView> </ListView. view> </ListView> </Grid> </Window>View Code
There are not many changes. The Student class adds the Score attribute, adds the Score column template to the DataTemplate, and adds some default scores to the data source.
Now that the data is ready, the following is the sorting function. First, write a sorting function: StuSort (string sortBy, ListSortDirection direction). The sorting function is implemented through the CollectionViewSource class, I will not introduce this class. You can sort and group data sources. For details, refer to MSDN. The Code is as follows:
Private void StuSort (ListView lv, string sortBy, ListSortDirection ction) {ICollectionView dataView = CollectionViewSource. getDefaultView (lv. itemsSource); // obtain the data source view dataView. sortDescriptions. clear (); // Clear the default sorting description SortDescription sd = new SortDescription (sortBy, direction); dataView. sortDescriptions. add (sd); // Add a new sort description dataView. refresh (); // Refresh view}
After writing the function, we will introduce the three parameters of this function. The first is undoubtedly that the data carries the ListView, and the second is more important to sort the data by the field, in this example, the Score is sorted by Student, so it is "Score". The third parameter is the sorting direction, ascending or descending. Then, this function is triggered when we click the Header of ListView. Monitor the routing event of GridViewColumnHeaderClick in the ListView on The Xaml page,
<ListView x: Name = "ListViewStudent"
ItemsSource = "{StaticResource stuList }"
GridViewColumnHeader. Click = "GridViewColumnHeaderClickedHandler"
>
The following code implements the GridViewColumnHeaderClickedHandler event in the background:
private void GridViewColumnHeaderClickedHandler(object sender, RoutedEventArgs e) { GridViewColumnHeader gch=e.OriginalSource as GridViewColumnHeader; StuSort(this.ListViewStudent, "Score", ListSortDirection.Ascending); }
Run, standalone score, to achieve sorting.
Ii. ListView with powerful view Functions
ListView can provide different View function switching, but only the GridView is provided by default. Can we customize our own View? The answer is yes. I will not elaborate on it because the Microsoft example is already good, http://msdn.microsoft.com/zh-cn/library/vstudio/ms771469 (v = vs.90). aspx. Detailed Description: a total of four custom views are provided.
How does WPF obtain the control of cells in the ListView?
We do not recommend that you bind the ItemsSource to the source. the number of Items sets varies randomly. The control of each cell depends on the default DataTemplate (when DisplayMemberBinding is set), the control defined by CellTemplate, or the control defined by the Template specified by CellTemplateSelector. using rowIndex and cellIndex to obtain a cell control is not a good solution. you can capture changes on the data layer, and then judge whether new values should be used based on the changed values, instead of making efforts on the UI elements. ------------------ back to the problem, to obtain, you must understand. listView is an Items Control. every Item of it is carried by ListViewItem as a container. listViewListViewItem1ListViewItem 2. Even if the DataTemplate does not use ListViewItem, The ListViewItem is used to hold it when the ListView is displayed. for ListView with GridView, the control tree structure of each ListViewItem is shown below: ListViewItem (default, non-styled) borderGridViewRowPresenterContentPresenter 1: Control 1 used to hold data (this is the target control in your problem, cell 1) ContentPresenter 2: Control 2 used to hold data (Cell 2) contentPresenter N is the control N (cell N) used to hold data. Obviously, the Content of ContentPresenter is what we get. the following function is available: private UIElement GetListViewCel LControl (int rowIndex, int cellIndex) {// rowIndex and cellIndex are based on 0. // first obtain the ListViewItem. Undoubtedly, all visual UI elements inherit the UIElement: UIElement u = lv. itemContainerGenerator. containerFromIndex (rowIndex) as UIElement; if (u = null) return null; // then search for cells in the ListViewItem element tree: while (u = (VisualTreeHelper. getChild (u, 0) as UIElement ))! = Null) if (u is GridViewRowPresenter) return VisualTreeHelper. getChild (VisualTreeHelper. getChild (u, cellIndex), 0) as UIElement; return u;} This function returns the cell control, which is a UIElement, if your ememplate uses TextBox to carry data, its return value is a TextBox. If you use CheckBox to carry data, its return value is a CheckBox, and so on, for example: textBox t = GetListViewCellControl (1, 2) as TextBox ;...... remaining full text>