WPF学习笔记-数据采集与监控项目03-课程总览(ItemsControl控件)
以下是学习笔记:
https://www.bilibili.com/video/BV1gq4y1D76d?p=57&spm_id_from=pageDriver&vd_source=3f21d2e208ef0bf2c49a9be7560735e5
重点内容:学习课程总览的数据绑定
1,滚动页面效果:
把页面放入ScrollViewer中
2,课程总览的页面
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | <!--课程总览,第3行--> <Grid Margin= "10,0" Grid.Row= "2" > <Grid.RowDefinitions> <RowDefinition Height= "40" /> <RowDefinition/> </Grid.RowDefinitions> <!--第一行的标题--> <TextBlock Text= "课程总览" Foreground= "#3f4c5d" VerticalAlignment= "Center" FontSize= "15" FontWeight= "Bold" /> <TextBlock HorizontalAlignment= "right" VerticalAlignment= "Center" > <Hyperlink FontSize= "15" >详情</Hyperlink> </TextBlock> <!--第二行的课程展示,这个最重要--> <ItemsControl ItemsSource= "{Binding CourseSeriesList}" Grid.Row= "1" > <!--需要修改容器模板--> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <VirtualizingStackPanel/> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemTemplate> <DataTemplate> <Border Background= "White" CornerRadius= "10" > <Border.Effect> <DropShadowEffect Color= "Gray" ShadowDepth= "0" BlurRadius= "10" Opacity= "0.2" Direction= "0" ></DropShadowEffect> </Border.Effect> <Grid Height= "70" > <!--分成三列--> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> <ColumnDefinition Width= "3.5*" /> </Grid.ColumnDefinitions> <!--三列之间的分割竖线--> <Border BorderBrush= "#ddd" BorderThickness= "0,0,1,0" Margin= "0,10" /> <Border BorderBrush= "#ddd" BorderThickness= "0,0,1,0" Margin= "0,10" Grid.Column= "1" /> <!--第一列--> <TextBlock Text= "{Binding CourseName}" VerticalAlignment= "Center" HorizontalAlignment= "Center" Foreground= "#444" /> <!--第二列--> <lvc:PieChart Grid.Column= "1" LegendLocation= "Right" InnerRadius= "10" Margin= "0,0,10,0" Series= "{Binding SeriesCollection}" > <!--<lvc:PieChart.Series>--> <!--<lvcs:SeriesCollection> <lvc:PieSeries Title= "111" Values= "12" DataLabels= "False" /> <lvc:PieSeries Title= "111" Values= "12" DataLabels= "False" /> <lvc:PieSeries Title= "111" Values= "12" DataLabels= "False" /> <lvc:PieSeries Title= "111" Values= "12" DataLabels= "False" /> <lvc:PieSeries Title= "111" Values= "12" DataLabels= "False" /> </lvcs:SeriesCollection> </lvc:PieChart.Series>--> <lvc:PieChart.ChartLegend> <lvc:DefaultLegend BulletSize= "10" /> </lvc:PieChart.ChartLegend> <lvc:PieChart.DataTooltip> <lvc:DefaultLegend BulletSize= "10" /> </lvc:PieChart.DataTooltip> </lvc:PieChart> <!--第三列--> <ItemsControl Grid.Column= "2" ItemsSource= "{Binding SeriesLsit}" > <!--修改控件模板--> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <!--设置列数,超过5列自动换行--> <!--<UniformGrid Columns= "5" />--> <!--设置动态的列数--> <UniformGrid Columns= "{Binding DataContext.ItemCount,RelativeSource={RelativeSource AncestorType=UserControl,Mode=FindAncestor}}" /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemTemplate> <DataTemplate> <Grid VerticalAlignment= "Center" HorizontalAlignment= "Center" > <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition MinHeight= "24" /> <RowDefinition MinHeight= "24" /> </Grid.RowDefinitions> <TextBlock Text= "{Binding SeriesName}" VerticalAlignment= "Center" /> <TextBlock Text= "{Binding CurrentValue}" Grid.Row= "1" VerticalAlignment= "Center" /> <TextBlock Text= "{Binding IsGrowing ,Converter={StaticResource BoolToArrowConverter_suibian}}" Foreground= "{Binding IsGrowing,Converter={StaticResource BoolToBrushConverter_suibian}}" Grid.Column= "1" VerticalAlignment= "Center" Margin= "10,0,0,0" /> <TextBlock Text= "{Binding ChangeRate}" Grid.Column= "1" Foreground= "{Binding IsGrowing,Converter={StaticResource BoolToBrushConverter_suibian}}" Grid.Row= "1" VerticalAlignment= "Center" Margin= "10,0,0,0" /> </Grid> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> <!--第三列的原始草稿模板--> <!--<UniformGrid Columns= "5" Grid.Column= "2" > <Grid VerticalAlignment= "Center" HorizontalAlignment= "Center" > <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition/> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition/> <RowDefinition/> </Grid.RowDefinitions> <TextBlock Text= "云课堂" /> <TextBlock Text= "161" Grid.Row= "1" /> <TextBlock Text= "|" Grid.Column= "1" /> <TextBlock Text= "75%" Grid.Column= "1" Grid.Row= "1" /> </Grid> </UniformGrid>--> </Grid> </Border> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> |
3,Model
1 2 3 4 5 6 7 8 9 | /// <summary> /// 课程类 /// </summary> public class CourseServiceModel { public string CourseName { get ; set ; } public SeriesCollection SeriesCollection { get ; set ; } public ObservableCollection<SeriesModel> SeriesLsit { get ; set ; } } |
4,ViewModel
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 | public class FirstPageViewModel:NotifyBase { private int _instrumentValue=0; public int InstrumentValue { get { return _instrumentValue; } set { _instrumentValue = value; this .DoNotify(); } } private int _itemCount; //设置一个变量,给一个动态数量排列 public int ItemCount { get { return _itemCount; } set { _itemCount = value; this .DoNotify(); } } /// <summary> /// 课程集合 /// </summary> public ObservableCollection<CourseServiceModel> CourseSeriesList { get ; set ; }= new ObservableCollection<CourseServiceModel>(); Random random= new Random(); /// <summary> /// 线程的开关 /// </summary> private bool taskSwitch= true ; /// <summary> /// 开启的线程集合 /// </summary> List<Task> tasklList= new List<Task>(); public FirstPageViewModel() { this .RefreshInstrumentValue(); this .InitCourseSeries(); } void InitCourseSeries() { #region 测试添加数据 //CourseSeriesList.Add(new CourseServiceModel() //{ // CourseName = "Java从入门到放弃", // SeriesCollection = new SeriesCollection() // { // new PieSeries() // { // Title = "1111", // Values = new ChartValues<ObservableValue> {(new ObservableValue(10))}, // DataLabels = false, // }, // new PieSeries() // { // Title = "2222", // Values = new ChartValues<ObservableValue> {(new ObservableValue(20))}, // DataLabels = false, // }, // new PieSeries() // { // Title = "3333", // Values = new ChartValues<ObservableValue> {(new ObservableValue(30))}, // DataLabels = false, // }, // new PieSeries() // { // Title = "4444", // Values = new ChartValues<ObservableValue> {(new ObservableValue(40))}, // DataLabels = false, // }, // }, // SeriesLsit = new ObservableCollection<SeriesModel>() // { // new SeriesModel(){SeriesName = "云课堂1",CurrentValue = 161,IsGrowing = false,ChangeRate = 75}, // new SeriesModel(){SeriesName = "云课堂2",CurrentValue = 161,IsGrowing = true,ChangeRate = 50}, // new SeriesModel(){SeriesName = "云课堂3",CurrentValue = 161,IsGrowing = false,ChangeRate = 90}, // new SeriesModel(){SeriesName = "云课堂4",CurrentValue = 161,IsGrowing = true,ChangeRate = 85}, // new SeriesModel(){SeriesName = "云课堂5",CurrentValue = 161,IsGrowing = false,ChangeRate = 78}, // } //}); //CourseSeriesList.Add(new CourseServiceModel() //{ // CourseName = "Java从入门到放弃", // SeriesCollection = new SeriesCollection() // { // new PieSeries() // { // Title = "1111", // Values = new ChartValues<ObservableValue> {(new ObservableValue(10))}, // DataLabels = false, // }, // new PieSeries() // { // Title = "2222", // Values = new ChartValues<ObservableValue> {(new ObservableValue(20))}, // DataLabels = false, // }, // new PieSeries() // { // Title = "3333", // Values = new ChartValues<ObservableValue> {(new ObservableValue(30))}, // DataLabels = false, // }, // new PieSeries() // { // Title = "4444", // Values = new ChartValues<ObservableValue> {(new ObservableValue(40))}, // DataLabels = false, // }, // }, // SeriesLsit = new ObservableCollection<SeriesModel>() // { // new SeriesModel(){SeriesName = "云课堂1",CurrentValue = 161,IsGrowing = false,ChangeRate = 75}, // new SeriesModel(){SeriesName = "云课堂2",CurrentValue = 161,IsGrowing = true,ChangeRate = 50}, // new SeriesModel(){SeriesName = "云课堂3",CurrentValue = 161,IsGrowing = false,ChangeRate = 90}, // new SeriesModel(){SeriesName = "云课堂4",CurrentValue = 161,IsGrowing = true,ChangeRate = 85}, // new SeriesModel(){SeriesName = "云课堂5",CurrentValue = 161,IsGrowing = false,ChangeRate = 78}, // new SeriesModel(){SeriesName = "其他",CurrentValue = 161,IsGrowing = false,ChangeRate = 78}, // } //}); #endregion var cList = LocalDataAccess.GetInstance().GetCoursePlayRecord(); //获取最大的数量 this .ItemCount = cList.Max(c => c.SeriesLsit.Count); //【特别注意】用这个方式,相当于把之前的对象替换掉了,页面接收不到数据的 //this.CourseSeriesList = new ObservableCollection<CourseServiceModel>(cList); //要使用CourseSeriesList.Add(item)方式,页面才能接收到数据 foreach ( var item in cList) { this .CourseSeriesList.Add(item); } } void RefreshInstrumentValue() { var task = Task.Factory.StartNew( new Action(async () => { while (taskSwitch) { //0和100是最大值和最小值,这里为了演示效果是写死的,后期可用变量替代。 InstrumentValue = random.Next(Math.Max( this .InstrumentValue - 5,0), Math.Min( this .InstrumentValue + 5,100)); //停顿1秒刷新 await Task.Delay(1000); } })); tasklList.Add(task); } public void Dispose() { try { taskSwitch = false ; //等待所有线程结束 Task.WaitAll( this .tasklList.ToArray()); } catch (Exception e) { } } } |
5,数据的查询
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | public List<CourseServiceModel> GetCoursePlayRecord() { try { List<CourseServiceModel> cModelList = new List<CourseServiceModel>(); if (DBConnection()) { string userSql = @"select a.course_name,a.course_id ,b.play_count,b.is_growing,b.growing_rate , c.platforms_name from courses a left join play_record b on a.course_id = b.course_id left join platforms c on b.platform_id = c.platforms_id order by a.course_id,c.platforms_id" ; adapter = new SqlDataAdapter(userSql, conn); DataTable table = new DataTable(); int count = adapter.Fill(table); string courseId = "" ; CourseServiceModel cModel = null ; foreach (DataRow dr in table.AsEnumerable()) { string tempId = dr.Field< string >( "course_id" ); if (courseId != tempId) { courseId = tempId; cModel = new CourseServiceModel(); cModelList.Add(cModel); cModel.CourseName = dr.Field< string >( "course_name" ); cModel.SeriesCollection = new LiveCharts.SeriesCollection(); cModel.SeriesLsit = new ObservableCollection<SeriesModel>(); } if (cModel != null ) { cModel.SeriesCollection.Add( new PieSeries() { Title = dr.Field< string >( "platforms_name" ), Values = new ChartValues<ObservableValue> {( new ObservableValue(dr.Field< int >( "play_count" )))}, DataLabels = false }); } cModel.SeriesLsit.Add( new SeriesModel() { SeriesName = dr.Field< string >( "platforms_name" ), CurrentValue = dr.Field< int >( "play_count" ), IsGrowing = dr.Field< int >( "is_growing" ) == 1, ChangeRate = dr.Field< int >( "growing_rate" ), }); } } return cModelList; } catch (Exception e) { throw e; } finally { this .Dispose(); } } |
单选框效果
1,控件模板
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <UserControl.Resources> <ControlTemplate TargetType= "RadioButton" x:Key= "CategoryItemButtonTemplate" > <!--定义视觉树--> <Grid Background= "Transparent" Margin= "10,0" > <Border Background= "#eee" CornerRadius= "5" Name= "back" > <TextBlock Text= "{TemplateBinding Content}" Margin= "15,6" VerticalAlignment= "Center" HorizontalAlignment= "Center" /> </Border> </Grid> <!--定义视觉树_End--> <!--定义触发器--> <ControlTemplate.Triggers> <Trigger Property= "IsChecked" Value= "True" > <Setter Property= "Background" Value= "Orange" TargetName= "back" /> <Setter Property= "Foreground" Value= "white" /> </Trigger> </ControlTemplate.Triggers> <!--定义触发器_End--> </ControlTemplate> </UserControl.Resources> |
2,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | <StackPanel Orientation= "Horizontal" VerticalAlignment= "Center" > <TextBlock Text= "课程分类" VerticalAlignment= "Center" /> <!--ItemsSource用来数据绑定--> <ItemsControl ItemsSource= "{Binding CategoryCourses}" > <!--布局进行控制的面板--> <ItemsControl.ItemsPanel> <!--控件的容器外观--> <ItemsPanelTemplate> <StackPanel Orientation= "Horizontal" /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemTemplate> <!--数据模板--> <DataTemplate> <!--使用分组GroupName= "course" 使每一行相互隔离--> <RadioButton Content= "{Binding CategoryName}" IsChecked= "{Binding IsSelected}" Template= "{StaticResource CategoryItemButtonTemplate}" GroupName= "course" /> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </StackPanel> <StackPanel Orientation= "Horizontal" Grid.Row= "1" VerticalAlignment= "Center" > <TextBlock Text= "技术分类" VerticalAlignment= "Center" /> <ItemsControl ItemsSource= "{Binding CategoryTechnology}" > <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <StackPanel Orientation= "Horizontal" /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemTemplate> <DataTemplate> <RadioButton Content= "{Binding CategoryName}" IsChecked= "{Binding IsSelected}" Template= "{StaticResource CategoryItemButtonTemplate}" GroupName= "technology" /> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </StackPanel> <StackPanel Orientation= "Horizontal" Grid.Row= "2" VerticalAlignment= "Center" > <TextBlock Text= "授课老师" VerticalAlignment= "Center" /> <ItemsControl ItemsSource= "{Binding CategoryTeacher}" > <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <StackPanel Orientation= "Horizontal" /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> <ItemsControl.ItemTemplate> <DataTemplate> <RadioButton Content= "{Binding CategoryName}" IsChecked= "{Binding IsSelected}" Template= "{StaticResource CategoryItemButtonTemplate}" GroupName= "teacher" /> </DataTemplate> </ItemsControl.ItemTemplate> </ItemsControl> </StackPanel> |
3,
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | public class CoursePageViewModel { public ObservableCollection<CategoryItemModel> CategoryCourses { get ; set ; } public ObservableCollection<CategoryItemModel> CategoryTechnology { get ; set ; } public ObservableCollection<CategoryItemModel> CategoryTeacher { get ; set ; } public CoursePageViewModel() { this .CategoryCourses = new ObservableCollection<CategoryItemModel>(); this .CategoryCourses.Add( new CategoryItemModel( "全部" , true )); this .CategoryCourses.Add( new CategoryItemModel( "公开课" )); this .CategoryCourses.Add( new CategoryItemModel( "VIP课程" )); this .CategoryTechnology = new ObservableCollection<CategoryItemModel>(); this .CategoryTechnology.Add( new CategoryItemModel( "全部" , true )); this .CategoryTechnology.Add( new CategoryItemModel( "C#" )); this .CategoryTechnology.Add( new CategoryItemModel( "Python" )); this .CategoryTeacher = new ObservableCollection<CategoryItemModel>(); this .CategoryTeacher.Add( new CategoryItemModel( "全部" , true )); this .CategoryTeacher.Add( new CategoryItemModel( "Jason" )); this .CategoryTeacher.Add( new CategoryItemModel( "Mason" )); } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现