EpgTimerの予約一覧画面に「今日の予約数：xx件」という表示を追加する方法

こんな表示を追加します。

![imgTemp-2016-07-25-04-22-10.png](https://qiita-image-store.s3.amazonaws.com/0/5825/6e8f3125-303e-da2d-5956-a152dda6ced1.png)

対象バージョンはこちら。多分ほかのバージョンでも使えると思う。
[EDCB/EpgTimer/EpgTimer at 54137f00d0ee78135f6487027f9cf9040c93e244 · abt8WG/EDCB](https://github.com/abt8WG/EDCB/tree/54137f00d0ee78135f6487027f9cf9040c93e244/EpgTimer/EpgTimer)

やり方は単純で、シングルトンのクラスを作る。予約情報の更新時と、予約一覧画面の表示時に処理を追加する。


追加するクラス

```cs:/EpgTimer/EpgTimer/Common/ReserveInfoManager.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace EpgTimer.Common {
    class ReserveInfoManager {
        public static ReserveInfoManager Instance = new ReserveInfoManager();
        class OneItem {
            private String mDisplayText;
            private DateTime mDisplayLimitTime;
            private int mNormalCount = 0;
            private TimeSpan nNormalTimeSpan = new TimeSpan();
            private int mWarnCount = 0;
            private int mErrorCount = 0;
            private int mDisableCount = 0;
            public OneItem(String displayText, DateTime displayLimitTime) {
                this.mDisplayLimitTime = displayLimitTime;
                this.mDisplayText = displayText;
            }
            public void setOneReserve(DateTime reserveTime, TimeSpan reserveTimeSpan, PROGRAM_STATUS status) {
                if (mDisplayLimitTime < reserveTime) {
                    return;
                }
                switch (status) {
                    case PROGRAM_STATUS.DISABLE:
                        mDisableCount++;
                        break;
                    case PROGRAM_STATUS.NORMAL:
                        nNormalTimeSpan += reserveTimeSpan;
                        mNormalCount++;
                        break;
                    case PROGRAM_STATUS.WARN:
                        mWarnCount++;
                        break;
                    case PROGRAM_STATUS.ERROR:
                        mErrorCount++;
                        break;
                }
            }
            public void setLog(StringBuilder sb) {
                sb.Append(mDisplayText);
                sb.Append(":");
                sb.AppendFormat("合計録画時間:{0,3}時間{1:00}分間 ", (int)nNormalTimeSpan.TotalHours, (int)nNormalTimeSpan.Minutes);
                sb.AppendFormat("正常:{0,4}番組 ", mNormalCount);
                sb.AppendFormat("警告:{0,3}番組 ", mWarnCount);
                sb.AppendFormat("異常:{0,3}番組 ", mErrorCount);
                sb.AppendFormat("無効:{0,3}番組", mDisableCount);
            }
        }

        enum PROGRAM_STATUS {
            DISABLE,
            NORMAL,
            WARN,
            ERROR
        }
        List<OneItem> mSubItems = new List<OneItem>();
        internal void addReserveDatas(List<ReserveData> list) {
            //時刻のセット
            DateTime now = DateTime.Now;
            mSubItems.Clear();
            {
                DateTime setTime = now;
                if (6 <= setTime.Hour) {
                    setTime = setTime.Date.AddDays(1).AddHours(6);
                } else {
                    setTime = setTime.Date.AddHours(6);
                }
                mSubItems.Add(new OneItem("   朝6時", setTime));
            }
            mSubItems.Add(new OneItem("  今日中", now.Date.AddDays(1)));
            mSubItems.Add(new OneItem("24時間中", now.AddDays(1)));
            mSubItems.Add(new OneItem("48時間中", now.AddDays(2)));
            mSubItems.Add(new OneItem("72時間中", now.AddDays(3)));
            mSubItems.Add(new OneItem("    合計", now.AddYears(1)));
            list.ForEach((info) => {
                ReserveItem item = new ReserveItem(info);
                // Common\CommonManagerClass.cs#443 付近より
                // RecMode 0x00 = 全サービス
                // RecMode 0x01 = 指定サービス
                // RecMode 0x02 = 全サービス（デコード処理なし）
                // RecMode 0x03 = 指定サービス（デコード処理なし）
                // RecMode 0x04 = 視聴
                // RecMode 0x05 = 無効
                // Common\CtrlCmdDef.cs#377 付近より
                // かぶり状態 1:かぶってチューナー足りない予約あり 2:チューナー足りなくて予約できない
                if (info.RecSetting.RecMode == 5) { // 無効
                    this.addReserve(info.StartTime, TimeSpan.FromSeconds(info.DurationSecond), PROGRAM_STATUS.DISABLE);
                } else if (info.OverlapMode == 1) { // 黄
                    this.addReserve(info.StartTime, TimeSpan.FromSeconds(info.DurationSecond), PROGRAM_STATUS.WARN);
                } else if (info.OverlapMode == 2) { // 赤
                    this.addReserve(info.StartTime, TimeSpan.FromSeconds(info.DurationSecond), PROGRAM_STATUS.ERROR);
                } else {//通常
                    this.addReserve(info.StartTime, TimeSpan.FromSeconds(info.DurationSecond), PROGRAM_STATUS.NORMAL);
                }
            });
        }
        void addReserve(DateTime reserveTime, TimeSpan reserveTimeSpan, PROGRAM_STATUS status) {
            foreach (var item in mSubItems) {
                item.setOneReserve(reserveTime, reserveTimeSpan, status);
            }
        }
        public String getAllLog() {
            StringBuilder sb = new StringBuilder();
            foreach (var item in mSubItems) {
                item.setLog(sb);
                sb.Append("\r\n");
            }
            return sb.ToString().TrimEnd();
        }

    }
}

```


DBManagerClassの処理に割り込んでデータを横取り

```cs:EpgTimer/EpgTimer/Common/DBManagerClass.cs#442付近
                     list.ForEach(info => reserveList.Add(info.ReserveID, info));
                     list2.ForEach(info => tunerReserveList.Add(info.tunerID, info));
+                    Common.ReserveInfoManager.Instance.addReserveDatas(list);

                     updateReserveInfo = false;
                 }
```

後は必要な箇所でtextboxを追加して、画面の作成時とデータの更新時にシングルトンからテキストを取得する


```xml:EpgTimer/EpgTimer/ReserveView.xaml
             <Button Name="button_add_manual"    Content="プログラム予約追加" Margin="0,10" />
             <Button Name="button_timeShiftPlay" Content="追っかけ再生"       Margin="0,10" />
         </StackPanel>
+        <TextBox DockPanel.Dock="Top" Height="90" Name="textbox_reserve_detail" FontFamily="MS Gothic"></TextBox>^M
         <ListView Name="listView_reserve" Style="{StaticResource DataListViewStyle}" >
             <ListView.View>
                 <GridView x:Name="gridView_reserve" />
```

```cs:EpgTimer/EpgTimer/ReserveView.xaml.cs#70付近
                 //コンテキストメニューを開く時の設定
                 listView_reserve.ContextMenu.Opened += new RoutedEventHandler(mc.SupportContextMenuLoading);
+
+                this.textbox_reserve_detail.Text = Common.ReserveInfoManager.Instance.getAllLog();
             }
             catch (Exception ex) { MessageBox.Show(ex.Message + "\r\n" + ex.StackTrace); }
```

```cs:EpgTimer/EpgTimer/ReserveView.xaml.cs#84付近
        protected override bool ReloadInfoData()
        {
+            this.textbox_reserve_detail.Text = Common.ReserveInfoManager.Instance.getAllLog();
            return lstCtrl.ReloadInfoData(dataList =>
```

使用予定チューナー画面にも追加する

```xml:EpgTimer/EpgTimer/TunerReserveViewCtrl/TunerReserveMainView.xaml
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="auto" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="90" />
            <RowDefinition Height="auto" />
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
        <TextBox Grid.ColumnSpan="2" Height="90" Name="textbox_reserve_detail" FontFamily="MS Gothic"></TextBox>
        <my:TunerReserveTimeView Grid.Row="2" x:Name="tunerReserveTimeView" Margin="0,0,0,18" MouseRightButtonUp="sub_erea_MouseRightButtonUp" />
        <my:TunerReserveNameView Grid.Row="1" Grid.Column="1" x:Name="tunerReserveNameView" Margin="0,0,18,0" MouseRightButtonUp="sub_erea_MouseRightButtonUp" />
        <my:TunerReserveView Grid.Column="1" Grid.Row="2" x:Name="tunerReserveView" />
    </Grid>
```


```cs:EpgTimer/EpgTimer/TunerReserveViewCtrl/TunerReserveMainView.xaml.cs
イニシャライザの処理の最後に
           this.textbox_reserve_detail.Text = Common.ReserveInfoManager.Instance.getAllLog();

 ReloadReserveViewItem()の中に
                tunerList.Clear();
                reserveList.Clear();
+               this.textbox_reserve_detail.Text = Common.ReserveInfoManager.Instance.getAllLog();
                List<TunerReserveInfo> tunerReserveList = CommonManager.Instance.DB.TunerReserveList.Values
                    .OrderBy(info => info.tunerID).ToList();//多分大丈夫だけど一応ソートしておく

```

全てよし。こういうのってqiitaでやっていいもんですかね・・・