WPF分页写法(MVVM实现)

    管理员 112 1

    实现效果如下图(WPF重写DataGrid去掉边框以及表头
    Image

    1. 新建一个基类,实现双向通知(绑定)
    public class PropertyChangedBase : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
            protected void NotifyPropertyChanged([CallerMemberName]string propertyName = null)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
            protected bool SetProperty<T>(ref T backingStore, T value, [CallerMemberName]string propertyName = "", Action onChanged = null)
            {
                if (EqualityComparer<T>.Default.Equals(backingStore, value))
                    return false;
    
                backingStore = value;
                onChanged?.Invoke();
                NotifyPropertyChanged(propertyName);
                return true;
            }
        }
    1. 建立SSviewModel继承PropertyChangedBase
    public class SSViewModel : PropertyChangedBase
    {
            /// <summary>
            /// 历史数据列表(选中的设备)
            /// </summary>
            public ObservableCollection<CheckHisData> CheckHisDataList { get; set; }
    
            private int selectHisCurrentIndex;
            /// <summary>
            /// 页码变更事件
            /// </summary>
            public int SelectHisCurrentIndex
            {
                get => selectHisCurrentIndex; set => SetProperty(ref selectHisCurrentIndex, value, "", () =>
                {
                    GetHisData(SelectHisStartTime, SelectHisEndTime, selectHisCurrentIndex, SelectHisInterval, SelectHisStandard);
                });
            }
            
            /// <summary>
            /// 获取历史数据函数
            /// 委托(将函数委托) 以方便在SSviewModel中调用
            /// </summary>
            public Action<DateTime, DateTime, int, int, bool> GetHisData { get; set; }
    }
    

    页面Xaml代码:
    SelectHisCurrentIndex发生变化的时候,发生一系列变化。(所使用到UI库)WPF开源控件库《Panuon.UI.Silever》

                            <pu:Pagination
                                  x:Name="PageBtn"
                                  Grid.Row="1"
                                  Height="30"
                                  Margin="0,5,0,0"
                                  HorizontalAlignment="Center"
                                  VerticalAlignment="Center"
                                  CurrentIndex="{Binding SelectHisCurrentIndex, Mode=TwoWay}"
                                  TotalIndex="{Binding SelectHisTotalIndex, Mode=TwoWay}">
                                  <pu:Pagination.SideButtonStyle>
                                      <Style BasedOn="{StaticResource {x:Static purs:ResourceKeys.PaginationSideButtonStyle}}" TargetType="{x:Type RepeatButton}">
                                          <Setter Property="Control.Background" Value="#3388ff" />
                                          <Setter Property="pu:RepeatButtonHelper.HoverBrush" Value="#335fff" />
                                      </Style>
                                  </pu:Pagination.SideButtonStyle>
                                  <pu:Pagination.PaginationItemStyle>
                                      <Style BasedOn="{StaticResource {x:Static purs:ResourceKeys.PaginationItemStyle}}" TargetType="{x:Type RadioButton}">
                                          <Style.Triggers>
                                              <Trigger Property="pu:RadioButtonHelper.RadioButtonStyle" Value="Button">
                                                  <Setter Property="Control.Foreground" Value="White" />
                                                  <Setter Property="Control.Background" Value="#3388ff" />
                                                  <Setter Property="pu:RadioButtonHelper.CheckedBackground" Value="#335fff" />
                                              </Trigger>
                                          </Style.Triggers>
                                      </Style>
                                  </pu:Pagination.PaginationItemStyle>
                              </pu:Pagination>

    TODO:逻辑实现

            //Todo:以下业务实现
    
            /// <summary>
            /// 全局变量
            /// </summary>
            SSViewModel sSView = null;
    
            /// <summary>
            /// 获取服务器数据
            /// </summary>
            /// <param name="start">开始时间</param>
            /// <param name="end">结束时间</param>
            /// <param name="page">页码</param>
            /// <param name="interval">间隔</param>
            /// <param name="standard">只显示超标 默认false</param>
            private async void GetHisData(DateTime start, DateTime end, int page, int interval, bool standard)
            {
                #region 判断是否跨月,并是否支持跨月查询
                if (start > end)
                {
                    MessageBoxX.Show("开始时间不能大于结束时间。", "警 告", MessageBoxIcon.Warning);
                    return;
                }
                var handler = PendingBoxX.Show("加载服务器数据,请稍等(1/2)...", "Processing", false, Application.Current.MainWindow);
                await Task.Run(() =>
                {
                    #region 业务执行
                    var authenticationHeaderValue = new AuthenticationHeaderValue("bearer", CacheExt.GetCache("AccessToken"));
                    _client.DefaultRequestHeaders.Authorization = authenticationHeaderValue;
                    List<KeyValuePair<string, string>> param = new List<KeyValuePair<string, string>>();
                    param.Add(new KeyValuePair<string, string>("tabName", $"datalog{start.ToString("yyyyMM")}"));
                    var res = Client.Post("/api/system/GetCanRequest", _client, new FormUrlEncodedContent(param));
                    if (int.Parse(res["data"].ToString()) != 1)
                    {
                        //不支持跨月。判断时间是否跨月
                        if (start.Month != end.Month && start.Year != end.Year)
                        {
                            MessageBoxX.Show("当前用户不支持跨月查询", "警 告", MessageBoxIcon.Warning);
                            return;
                        }
                        else
                        {
                            param = new List<KeyValuePair<string, string>>();
                            param.Add(new KeyValuePair<string, string>("tabName", $"datalog{start.ToString("yyyyMM")}"));
                            param.Add(new KeyValuePair<string, string>("deviceNo", $"{sSView.SelectedDeviceNo.ToString()}"));
                            param.Add(new KeyValuePair<string, string>("startTime", $"{start.ToString("yyyy-MM-dd HH:mm:ss")}"));
                            param.Add(new KeyValuePair<string, string>("endTime", $"{end.ToString("yyyy-MM-dd HH:mm:ss")}"));
                            param.Add(new KeyValuePair<string, string>("interVal", $"{interval}"));
                            param.Add(new KeyValuePair<string, string>("standArd", $"{standard}"));
                            var hisList = Client.Post<HisDataInfo>("/api/data/PostHisDataList", _client, new FormUrlEncodedContent(param));
                            curveList.Clear();
                            curveList = hisList.HisDatas;
                            curveCount = hisList.HisDataCount;
                            if (hisList.HisDatas.Any())
                                SetList(hisList.HisDatas, hisList.HisDataCount, page);
                            else
                            {
                                MessageBoxX.Show("没有数据或查询失败", "警 告", MessageBoxIcon.Warning);
                                return;
                            }
                        }
                    }
                    else
                    {
                        //直接请求数据
                        param = new List<KeyValuePair<string, string>>();
                        param.Add(new KeyValuePair<string, string>("tabName", $"datalog{start.ToString("yyyyMM")}"));
                        param.Add(new KeyValuePair<string, string>("deviceNo", $"{sSView.SelectedDeviceNo.ToString()}"));
                        param.Add(new KeyValuePair<string, string>("startTime", $"{start.ToString("yyyy-MM-dd HH:mm:ss")}"));
                        param.Add(new KeyValuePair<string, string>("endTime", $"{end.ToString("yyyy-MM-dd HH:mm:ss")}"));
                        param.Add(new KeyValuePair<string, string>("interVal", $"{interval}"));
                        param.Add(new KeyValuePair<string, string>("standArd", $"{standard}"));
                        var hisList = Client.Post<HisDataInfo>("/api/data/PostHisDataList", _client, new FormUrlEncodedContent(param));
                        curveList.Clear();
                        curveList = hisList.HisDatas;
                        curveCount = hisList.HisDataCount;
                        if (hisList.HisDatas.Any())
                            SetList(hisList.HisDatas, hisList.HisDataCount, page);
                        else
                        {
                            MessageBoxX.Show("没有数据或查询失败", "警 告", MessageBoxIcon.Warning);
                            return;
                        }
                    }
                    #endregion
                });
                handler.UpdateMessage("正在完成,后续数据即将推送(2/2)。");
                handler.Close();
                #endregion
            }
    
          //TODO:调用了SetList函数(此处函数更新UI)
    
            /// <summary>
            /// 设置数据列表
            /// </summary>
            /// <param name="hisDatas"></param>
            /// <returns></returns>
            private ObservableCollection<SSViewModel.CheckHisData> SetList(List<HisData> hisDatas, HisDataCount count, int page)
            {
                #region 统计
                sSView.CheckHiss = new SSViewModel.CheckHis()
                {
                    HisCount = count.Counts.ToString(),
                    HisTemp = $"{(count.MaxTemp / 10.0).ToString("f1")} / {(count.MinTemp / 10.0).ToString("f1")}",
                    HisHumi = $"{(count.MaxHumi / 10.0).ToString("f1")} / {(count.MinHumi / 10.0).ToString("f1")}",
                    HisAvg = $"{(count.AvgTemp / 10.0).ToString("f1")} / {(count.AvgHumi / 10.0).ToString("f1")}"
                };
                //总页数
                sSView.SelectHisTotalIndex = (hisDatas.Count + 500 - 1) / 500;
                #endregion
                hisDatas = hisDatas.Skip((page - 1) * 500).Take(500).ToList();
                //清空
                Dispatcher.Invoke(() =>
                {
                    sSView.CheckHisDataList.Clear();
                });
                foreach (var item in hisDatas)
                {
                    SSViewModel.CheckHisData viewModel = new SSViewModel.CheckHisData()
                    {
                        Deviceno = item.DeviceNO,
                        DataTime = item.DataTime.ToString("yyyy-MM-dd HH:mm:ss"),
                        Humi = item.Humidity / 10.0,
                        Temp = item.Temperature / 10.0,
                        Standard = item.alarmstatus == 1 ? "超标" : ""
                    };
                    Dispatcher.Invoke(() =>
                    {
                        sSView.CheckHisDataList.Add(viewModel);
                    });
                }
                return sSView.CheckHisDataList;
            }
    
    
          //在此页面构造函数中将函数委托给SSviewModel
          sSView.GetHisData = GetHisData;  //此处

    思路逻辑如下:

    • 要通过MVVM实现分页,关键在页码变更的时候通知后台变更数据
    • 页码变更事件在SSviewModel里面,我们不能跨页面调用函数。所以此处用到了委托
    • GetHisData() 此函数仅仅是在服务器拉取数据,数据源下来之后,调用SetList()方法,更新UI
    • 请根据自己的业务逻辑自行调整相关代码

    有问题可以在下方留言。

      赞一个呗 3

      该篇文章所属“长情猫”原创所有,转载请注明本文链接

      已有 0 条评论