[WPF] 공공데이터 포털 API 이용 클라이언트 구현 Part 3

이미지
그룹핑 ListViewItem 그룹핑 할 수 있습니다. 먼저 CheckBox에 Checked 이벤트를 통해 그룹핑을 추가하고 RemoveChecked 이벤트를 통해 그룹핑을 제거 할 수 있도록 CheckBox를 선언 합니다. 1: <!-- Group CheckBox --> 2: <CheckBox Grid.Column="0" 3: Grid.Row="0" 4: Checked="AddGrouping" 5: Unchecked="RemoveGrouping">Group by Name</CheckBox> 그룹 스타일 선언 GroupStyle 속성에 ContainerStyle 속성을 이용해 Style을 지정 합니다. Expander 컨트롤을 이용해 아파트명과 그룹 아이템의 개수를 Expander Header에 표시 하도록 ControlTemlate를 선언 합니다. 1: <!-- Group Style --> 2: <ListView.GroupStyle> 3: <GroupStyle> 4: <GroupStyle.ContainerStyle> 5: <Style TargetType="{x:Type GroupItem}"> 6: <Setter Property="Margin" Value="0,0,0,5" /> 7: <Setter Property="Te...

[WPF] 날짜 계산 툴

WPF를 이용해 네이버가 제공하는 날짜 계산 기능을 구현해 보려 합니다.
(날짜 계산은 기준일을 1일로 포함하여 계산 됩니다)


위와 비슷한 형태로 구현을 하기 위해 필요한 기능이 무엇인지 확인 해볼께요.

  1. 달력에서 날짜 선택 시 [기준년월일]에 자동 입력
  2. [기준년월일] 유효성 검사
  3. [기준년월일]로 부터 날짜 더하기
  4. [기준년월일]로 부터 날짜 빼기
  5. [기준년월일]로 부터 기간 구하기

이렇게 필요할 듯 합니다.


이제 하나 하나 알아보도록 하겠습니다.


달력에서 날짜 선택 시 [기준년월일]에 자동 입력

Calendar 컨트롤과 기준년월일 입력에 필요한 텍스트 박스를 XAML 마크업을 이용해 선언 한 뒤 Calendar 컨트롤에서 SelectedDatesChanged 이벤트를 등록 합니다.

1:  <Calendar x:Name="calendar" BorderThickness="0" SelectedDatesChanged="Calendar_SelectedDatesChanged"/>  

유저가 날짜 선택 시 기준년월일에 선택 된 날짜를 텍스트 박스 Text 속성에 대입합니다.
1:  /// <summary>  
2:      /// 달력 컨트롤의 선택 날짜가 변경 되었을 경우 지정일에 선택된 날짜를 입력 합니다.  
3:      /// </summary>  
4:      /// <param name="sender"></param>  
5:      /// <param name="e"></param>  
6:      private void Calendar_SelectedDatesChanged(object sender, SelectionChangedEventArgs e)  
7:      {  
8:        if (calendar.SelectedDate.HasValue)  
9:        {  
10:          DateTime selectedItem = calendar.SelectedDate.Value;  
11:          txtBaseDate.Text = selectedItem.ToString(VALID_DATE_FORMAT);  
12:        }  
13:      }  

[기준년월일] 유효성 검사

  • 최대 길이 10
  • 유효한 문자("숫자", ".")만 입력 가능
  • 유요한 포맷("yyyy.MM.dd")만 가능
  • "숫자"(ex: 20180218) 형식으로 입력 되었을 경우 지정 날짜 포맷으로 변경
유효성에 필요한 상수 선언
1:   // 지정 날짜 문자열 최대 길이  
2:      private const Int32 VALID_DATE_MAX_LENGTH = 10;  
3:      // 지정 날짜 문자열 포맷  
4:      private const String VALID_DATE_FORMAT = "yyyy.MM.dd";  
5:      // 주(Week) 문자열 포맷  
6:      private const String VALID_DAY_OF_WEEK_FORMAT = "dddd";  
7:      // 숫자와 .만 가능 패턴  
8:      private const String VALID_INPUT_PATTERN = @"[\d.]$";  
9:      // 유효 날짜 패턴  
10:      private const String VALID_DATE_PATTERN = @"^\d{4}.\d{2}.\d{2}$";  
11:      // 날짜 입력 옵션 지원 패턴  
12:      private const String OPTION_DATE_PATTERN = @"^\d{8}$";  

최대 입력 길이 제한
1:  txtBaseDate.MaxLength = VALID_DATE_MAX_LENGTH;  


문자 입력 시 유효성 체크를 위해 TextChanged 이벤트 선언
1:  <TextBox x:Name="txtBaseDate" Grid.Row="1" Grid.Column="0" Margin="0,10" TextChanged="textBox_TextChanged"  />  

유효하지 않은 문자열 확인
1:  /// <summary>  
2:      /// 입력 후 발생되는 이벤트이다.   
3:      /// 숫자 또는 .만 가능하도록 확인한다.  
4:      /// </summary>  
5:      /// <param name="sender"></param>  
6:      /// <param name="e"></param>  
7:      private void textBox_TextChanged(object sender, TextChangedEventArgs e)  
8:      {  
9:        TextBox textBox = sender as TextBox;  
10:        string input = textBox.Text;  
11:        // 유효한 문자열 확인  
12:        if (Regex.IsMatch(input, VALID_INPUT_PATTERN) == false)  
13:        {  
14:          // 이전 문자열로 변경  
15:          textBox.Text = StringToPrevPosition(input);  
16:          textBox.CaretIndex = textBox.Text.Length;  
17:        }  
18:      }  

이전 문자열로 변경
1:  /// <summary>  
2:      /// 문자열을 이전으로 되돌립니다.  
3:      /// </summary>  
4:      /// <returns></returns>  
5:      private string StringToPrevPosition(string str)  
6:      {  
7:        return str.Substring(0, str.Length - 1);  
8:      }  

유효한 포맷 확인 및 옵션 지원 포맷 확인
1:  // 입력 문자열이 비어있는지 확인  
2:        if (string.IsNullOrEmpty(txtBaseDate.Text))  
3:        {  
4:          List<Inline> textBlockString = CreateGuideText();  
5:          txtResult.Inlines.AddRange(textBlockString);  
6:          return;  
7:        }  
8:        // yyyyMMdd 포맷인지 확인  
9:        if (Regex.IsMatch(txtBaseDate.Text, OPTION_DATE_PATTERN))  
10:        {  
11:          string validDateString = OptionDateStringToValidDateString(txtBaseDate.Text);  
12:          // 텍스트 박스의 문자열을 유요한 문자열로 변경  
13:          txtBaseDate.Text = validDateString;  
14:          txtBaseDate.CaretIndex = validDateString.Length;  
15:        }  
16:        // 유요한 포맷인지 확인  
17:        if (Regex.IsMatch(txtBaseDate.Text, VALID_DATE_PATTERN))  
18:        {  
19:          // 이 곳에서 날짜 계산 처리  
20:        }  

오늘 기준으로 [기준년월일] 기간 확인

기준년월일 문자열 속성 정의
1:  /// <summary>  
2:      /// 지정일 문자열을 날짜 형식으로 변경합니다.  
3:      /// </summary>  
4:      public DateTime? InputDate  
5:      {  
6:        get  
7:        {  
8:          if (string.IsNullOrEmpty(txtBaseDate.Text)) return null;  
9:          DateTime date = DateTime.MinValue;  
10:          if (DateTime.TryParse(txtBaseDate.Text, out date)) return date;  
11:          else return null;  
12:        }  
13:      }  

시작 날짜가 종료 날짜보다 크거나 같은지 여부
1:  /// <summary>  
2:      /// 시작 날짜가 종료 날짜보다 크거나 같은지 여부  
3:      /// </summary>  
4:      /// <param name="startDate"></param>  
5:      /// <param name="endDate"></param>  
6:      /// <returns></returns>  
7:      private bool IsSwap(DateTime startDate, DateTime endDate)  
8:      {  
9:        return (startDate >= endDate);  
10:      }  

시작 날짜와 종료 날짜의 기간을 계산합니다.
1:  /// <summary>  
2:      /// 시작 날짜와 종료 날짜의 기간을 계산합니다.  
3:      /// </summary>  
4:      /// <param name="startDate"></param>  
5:      /// <param name="endDate"></param>  
6:      /// <returns></returns>  
7:      private TimeSpan CalculatorDateTerm(DateTime startDate, DateTime endDate)  
8:      {  
9:        if (IsSwap(startDate, endDate))  
10:        {  
11:          DateTime tempDate = startDate;  
12:          startDate = endDate;  
13:          endDate = tempDate;  
14:        }  
15:        return endDate.Subtract(startDate);  
16:      }  

기준일로부터 ?일째 되는 날 구하기

1:  /// <summary>  
2:      /// 지정일로부터 날짜를 더합니다.  
3:      /// </summary>  
4:      /// <param name="sender"></param>  
5:      /// <param name="e"></param>  
6:      private void btnAddDay_Click(object sender, RoutedEventArgs e)  
7:      {  
8:        DateTime? dt = InputDate;  
9:        string addDay = txtAddDay.Text;  
10:        if (dt.HasValue && !string.IsNullOrEmpty(addDay))  
11:        {  
12:          DateTime addDate = dt.Value.AddDays(Convert.ToDouble(addDay));  
13:          txtAddDayResult.Text = addDate.ToString("yyyy.MM.dd");  
14:        }  
15:      }  

기준일로부터 D-?일 구하기

1:  /// <summary>  
2:      /// 지정일로부터 날짜를 뺍니다.  
3:      /// </summary>  
4:      /// <param name="sender"></param>  
5:      /// <param name="e"></param>  
6:      private void btnSubtract_Click(object sender, RoutedEventArgs e)  
7:      {  
8:        // 지정일부터 몇 일전  
9:        DateTime? dt = InputDate;  
10:        string subtractDay = txtSubtractDay.Text;  
11:        if (dt.HasValue && !string.IsNullOrEmpty(subtractDay))  
12:        {  
13:          DateTime subtractDate = dt.Value.AddDays(-Convert.ToDouble(subtractDay));  
14:          txtSubtractResult.Text = subtractDate.ToString("yyyy.MM.dd");  
15:        }  
16:      }  

기준일로부터 ?까지는 며칠 째 구하기

1:  /// <summary>  
2:      /// 지정일과 입력된 날짜의 일 간격을 계산 합니다.  
3:      /// </summary>  
4:      /// <param name="sender"></param>  
5:      /// <param name="e"></param>  
6:      private void btnTerm_Click(object sender, RoutedEventArgs e)  
7:      {  
8:        // 지정일로부터 기간  
9:        if (Regex.IsMatch(txtTermDay.Text, VALID_DATE_PATTERN))  
10:        {  
11:          DateTime? dt = InputDate;  
12:          DateTime startDate = DateTime.MinValue;  
13:          if (DateTime.TryParse(txtTermDay.Text, out startDate) && dt.HasValue)  
14:          {  
15:            TimeSpan term = CalculatorDateTerm(startDate, dt.Value);  
16:            int totalDay = term.Days;  
17:            totalDay = IsSwap(startDate, dt.Value) ? (totalDay += 1) : (totalDay * -1);  
18:            txtTermResult.Text = string.Format("{0}일째", totalDay);  
19:          }  
20:        }  
21:      }  


최종 결과


댓글

이 블로그의 인기 게시물

[C#] Task 완료 시 다른 Task를 자동으로 수행

[C#] 태스크(Task)가 완료될 때 까지 대기하여 결과를 얻는 방법

[C#] 명시적으로 Task 생성 및 실행