double과 바인딩하는 TextBox에 소수점을 입력 할 수 없습니다! 【완결편‼ 】

11241 단어 .NETWPFXamlMVVMC#

배경(전회까지의 개요)



double과 바인딩하는 TextBox에 소수점을 입력 할 수 없습니다!
double과 바인딩하는 TextBox에 소수점을 입력 할 수 없습니다! 【해결편⁉】
  • C# + XAML
  • TextBox가 숫자 형식의 속성과 바인딩되었습니다.
  • 실시간으로 입력 값으로 바인딩 된 속성 업데이트

  • 이대로는 소수부 입력에 문제가 있습니다. 거기서
  • 컨버터를 붙인
  • 이전과 다른 값이라면 서식 지정을 적용하여 TextBox에 다시 씁니다.
  • 이전과 같은 값이라면 입력 문자열을 그대로 TextBox로 씁니다.


  • 라고 했습니다만, 다음과 같은 경우, 역시 잘 작동하지 않습니다!
  • 정수 부분의 세 자리가 아닌 곳에 쉼표를 입력 할 수 있습니다.
  • 소수점 이하의 숫자를 편집해, 말미가 소수점이나 0이 되었을 경우, 이들이 사라져 버린다

  • 코멘트를 받았습니다!



    또, @albireo 씨에게 코멘트를 받았습니다! 감사합니다!

    서식 지정을 동적으로 변경!



    거기서 조금 발상을 바꾸어, 입력 캐릭터 라인을 그대로 되돌리려 하는 것이 아니라, 말미의 소수점이나 0이 나오도록(듯이), 입력 캐릭터 라인에 맞추어 서식 지정을 변경하기로 했습니다.
  • 기본적으로, 원래 지정된 서식 지정을 적용한다.
  • 이제 편하게 입력 된 쉼표를 제거 할 수 있습니다

  • 입력 캐릭터 라인의 마지막이 소수점이라면, 원래의 서식 지정의 정수부의 뒤에 소수점의 기호를 붙인 서식 지정을 적용한다
  • 이제 끝의 소수점을 출력 할 수 있습니다

  • 입력 캐릭터 라인에 소수부가 있는 경우, 원래의 서식 지정의 소수부를, 적어도 입력 캐릭터 라인의 소수부의 자리수를 출력하는 서식 지정에 바꾸어 적용한다
  • 이제 소수점 이하의 끝에 0을 출력 할 수 있습니다


  • 작동하는 모습





    입력에 따라 쉼표가 적절한 위치에 있음에 주목!

    코드



    XAML
    <TextBox Text="{Binding Path=Number,
                            Mode=TwoWay,
                            UpdateSourceTrigger=PropertyChanged,
                            Converter={StaticResource converter},
                            ConverterParameter='#,0.#####'}" />
    

    서식 지정을, 컨버터에의 인수 ConverterParameter 로 건네주고 있습니다.

    컨버터 클래스
    //doubleと文字列のコンバーター
    public class DoubleToStringConverter : System.Windows.Data.IValueConverter
    {
      private string convertBackString; //入力文字列
    
      //doubleから文字列への変換(表示時に使われる)
      public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
      {
        try
        {
          if (!(value is double)) return null;
    
          string format = (parameter as string) ?? string.Empty;
          if (!string.IsNullOrEmpty(convertBackString))
          {
            //フォーマットを「整数部」と「小数部」に分ける
            var formatParts = format.Split('.');
            if (formatParts.Length >= 2)
            {
              //入力文字列が小数点で終わっていたら、「整数部」+「小数点そのもの」をフォーマットにする
              if (convertBackString.EndsWith(culture.NumberFormat.NumberDecimalSeparator))
              {
                format = formatParts[0] + @"\" + culture.NumberFormat.NumberDecimalSeparator;
              }
              else
              {
                var pos = convertBackString.IndexOf(culture.NumberFormat.NumberDecimalSeparator);
                if (pos >= 0)
                {
                  //入力文字列に小数部があれば、「整数部」+「ピリオド」+「入力文字列の小数の桁数分の0」をフォーマットにする
                  var digitLength = convertBackString.Length - pos - 1;
                  format = formatParts[0] + @"."
                      + new string('0', digitLength)
                      + formatParts[1].Substring(Math.Min(digitLength, formatParts[1].Length));
                }
              }
            }
          }
          return ((double)value).ToString(format);
        }
        finally
        {
          convertBackString = null;
        }
      }
    
      //文字列からdoubleへの変換(入力時に使われる)
      public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
      {
        //入力文字列を保存する
        convertBackString = value as string;
    
        if (!string.IsNullOrEmpty(convertBackString)
          && double.TryParse(convertBackString, out double newValue))
        {
          //入力文字列をパーズして戻す
          return newValue;
        }
        else
        {
          return null;
        }
      }
    }
    

    컨버터가 내부 상태 convertBackString 를 가지고 있기 때문에, 같은 컨버터의 인스턴스를 복수의 TextBox 로 사용해 주면(자), 마즈일지도 모릅니다.

    소수점을 어떻게 표현하는지는 로케일에 따라 다릅니다. CultureInfo.NumberFormat.NumberDecimalSeparator 는 소수점 기호입니다.

    완결!



    일단, 완성으로 둡니다!

    서식 지정을 기술하는 것이 StringFormat 가 아닐까, 서식에 G 이나 F 등 표준의 서식 지정자가 지정되면 어떻게 할까라든지, 여러가지 츳코미는 있을 것이라고 생각합니다!

    개선안등이 있으면, 꼭, 코멘트해 주세요! 잘 부탁드립니다!

    좋은 웹페이지 즐겨찾기