none
FormatStringで「%」を表示せずパーセント表示したい RRS feed

  • 質問

  • お世話になります。
    実行環境はASP.NET MVCですが、内容的にはC#に近いと考え、こちらに投稿させていただきます。

    SqlServerのTable内で「占有率」を意味するフィールドがあり、データ型decimalとして「0.000~0.999」までの値を持っています。

    これをWebサイトでの表記上、DataFormatStringでパーセント表示したいのですが、当方の業務では「%」は表示しない慣習になっています。
    わかりにくいかもしれませんが、例えば内部のデータが「0.987」だった場合、

    占有率.Format("{0:#0.0%}")

    とする事で「98.7%」と表記するのが一般的ですが、
    当方の場合は「98.7」と表記しなければなりません。

    とりあえずTableをバインドするClass内に「占有率x100」を計算するプロパティを作り凌いでいますが、
    実際問題として率を示す項目が多いことと、もっとスマートな方法があればと思いご相談させていただきました。

    何かお知恵がありましたらよろしくお願いいたします。

    2019年9月6日 0:34

すべての返信

  • ASP.NET MVC の話であれば一般的な C# の質問ではなく、何を使って、どこに、どのように表示するかを含めて、ASP.NET MVC の質問とされた方が良さそうな気がしますが。

    余計なお世話でしたら失礼しました。

    2019年9月6日 1:05
  • %指定子はNumberFormatInfo::PercentSymbolに設定されているパーセント記号を埋め込むので、以下のようにすればパーセント記号を空文字にすることはできます。

    var culture = new CultureInfo(CultureInfo.CurrentCulture.LCID, true);
    culture.NumberFormat.PercentSymbol = "";
    CultureInfo.CurrentCulture = culture;
    
    Debug.WriteLine(String.Format("{0:#0.0%}", 0.1231M));
    // 結果: 12.3

    ただCurrentCultureはスレッド毎に設定されるので、もしバインディングが上記を行ったスレッドと別スレッドで行われるならこの方法は使えませんね。

    // NumberFormatInfoの既定値は大体Windowsの設定を取得してるんですが、パーセント記号はWindows10の地域の設定には含まれていませんでした。レジストリ漁ればあるのかな?

    • 回答の候補に設定 SurferOnWww 2019年9月6日 11:14
    2019年9月6日 1:09
  • お指摘ありがとうございます。

    内容的にはFormat関数の話なのでC#に投稿させていただきましたが、対策方法としてFormat関数にとどまらない可能性も考えると、やはりMVCの方が良かったかもしれません。判断を誤りました。

    2019年9月6日 1:28
  • Hongliangさんと基本的に同じですが、以下のテストコードで%を抑制できました。

    public partial class Percent書式テスト : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Thread.CurrentThread.CurrentCulture = new SuppressPercentSignCulture();
    
        }
    }
    
    public class SuppressPercentSignCulture : CultureInfo
    {
        public SuppressPercentSignCulture() : base(Thread.CurrentThread.CurrentCulture.Name)
        {
            this.NumberFormat.PercentSymbol = "";
        }
    }
    (追記)
    #MVCじゃなくてごめんなさい。MVCは不勉強なためよくわかりません。


    ★良い回答には質問者は回答済みマークを、閲覧者は投票を!


    2019年9月6日 1:41
    モデレータ
  • お二方、ご助言ありがとうございます。

    私がC#のスレッドに書いた事が問題なのですが、CurrentCultureを使った方法ですとControllerやClass内では上記の方法で可能なのですが、当方の場合Model側で下記のようにFormatを定義するため、同じようには出来なさそうです。

    [DisplayFormat(DataFormatString = "{0:#0.0%}")]
    public decimal Rate { get; set; }

    当初はFormatStringだけで簡単に出来るかもと安直に考えていましたが、別の方法を考えたいと思います。
    今回はありがとうございました。

    2019年9月6日 8:07
  • > 当方の場合Model側で下記のようにFormatを定義するため、同じようには出来なさそうです。

    実際にやってみて期待通りにいかなかったのですか?
    2019年9月6日 9:48
  • 試さないで諦めてることはないですか?

    試してみましたが、Hongliang さんが書かれたコードを Controller の Action Method に追加すれば期待通りに 12.3% が 12.3 になります。

    以下にどのように検証したか書いておきます。もし、実際にやってみて期待通りにいかなかったということであれば、これどどう違うのか連絡ください。

    Model

    public class AdInfo
    {
        public string Cn { get; set; }
        public string Name { get; set; }
        public string Mail { get; set; }
        public string Department { get; set; }
    
        [DisplayFormat(DataFormatString = "{0:#0.0%}")]
        public decimal Rate { get; set; }
    }

    View

    @model IEnumerable<Mvc5App.Models.AdInfo>
    
    @{
        ViewBag.Title = "AdInfo";
        Layout = "~/Views/Shared/_Layout.cshtml";
    }
    
    <h2>AdInfo</h2>
    
    <p>
        @Html.ActionLink("Create New", "Create")
    </p>
    <table class="table">
        <tr>
            <th>
                @Html.DisplayNameFor(model => model.Cn)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Name)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Mail)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Department)
            </th>
            <th>
                @Html.DisplayNameFor(model => model.Rate)
            </th>
            <th></th>
        </tr>
    
    @foreach (var item in Model) {
        <tr>
            <td>
                @Html.DisplayFor(modelItem => item.Cn)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Name)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Mail)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Department)
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Rate)
            </td>
            <td>
                @Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
                @Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
                @Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
            </td>
        </tr>
    }
    </table>

    Controller / Action Method

    public ActionResult AdInfo()
    {
        var culture = new CultureInfo(CultureInfo.CurrentCulture.LCID, true);
        culture.NumberFormat.PercentSymbol = "";
        CultureInfo.CurrentCulture = culture;
    
        List<AdInfo> model = new List<AdInfo>
        {
            new AdInfo { Cn = "ABC121", Name = "suzuki", Mail = "suzuki@jp", Department = "営業", Rate = 0.123m  },
            new AdInfo { Cn = "ABC122", Name = "sato", Mail = "sato@jp", Department = "総務", Rate = 0.234m },
            new AdInfo { Cn = "ABC123", Name = "tanaka", Mail = "tanaka@jp", Department = "経理", Rate = 0.345m }
        };
    
        return View(model);
    }

    実行結果

    注:CultureInfo の設定はグローバル化/ローカル化に影響があるかもしれませんので注意してください。詳しいことは、必要でしたら、聞いてください。

    2019年9月6日 11:12
  • Udukyさん、こんにちは。フォーラムオペレーターのHarukaです。
    MSDNフォーラムにご投稿くださいましてありがとうございます。

    ご質問いただいた件ですが、その後いかがでしょうか。
    Hongliangさんから寄せられた投稿はお役に立ちましたか。

    参考になった投稿には [回答としてマーク] をお願い致します。

    設定いただくことで、
    他のユーザーもお役に立つ回答を見つけやすくなります。

    お手数ですが、ご協力の程どうかよろしくお願いいたします。


    MSDN/ TechNet Community Support Haruka

    ~参考になった投稿には「回答としてマーク」をご設定ください。なかった場合は「回答としてマークされていない」も設定できます。同じ問題で後から参照した方が、情報を見つけやすくなりますので、
    ご協力くださいますようお願いいたします。また、MSDNサポートに賛辞や苦情がある場合は、MSDNFSF@microsoft.comまでお気軽にお問い合わせください。~

    2019年9月10日 1:02
    モデレータ