[wpf] كيف يمكنني تنسيق عشري منضم إلى TextBox دون إغضاب المستخدمين؟



0 Answers

لقد قمت بإنشاء السلوك المخصص التالي لنقل مؤشر المستخدمين إلى بعد StringFormat={}{0:0.00} العشرية عند استخدام StringFormat={}{0:0.00} ، مما يفرض مكانًا عشريًا ليكون موجودًا ، إلا أن هذا قد يتسبب في حدوث المشكلة التالية:

ينتهك الهدف 2. قل SomeDecimal 2.5 ويتم عرض مربع نص "2.50". إذا اخترنا الكل واكتبنا "13.5" ، فنحن ننتهي بـ "13.5.00" في مربع النص لأن المنسق "مفيد" يقوم بإدراج الكسور العشرية والأصفار.

لقد اخترقت هذا باستخدام سلوك مخصص سيؤدي إلى تحريك مؤشر المستخدمين إلى بعد المكان العشري عند الضغط على. مفتاح:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;

namespace GUI.Helpers.Behaviors
{
    public class DecimalPlaceHotkeyBehavior : Behavior<TextBox>
    {
        #region Methods
        protected override void OnAttached()
        {
            base.OnAttached();
            AssociatedObject.PreviewKeyDown += AssociatedObject_PreviewKeyDown;
        }

        protected override void OnDetaching()
        {
            base.OnDetaching();
            AssociatedObject.PreviewKeyDown -= AssociatedObject_PreviewKeyDown;
        }

        protected override Freezable CreateInstanceCore()
        {
            return new DecimalPlaceHotkeyBehavior();
        }
        #endregion

        #region Event Methods
        private void AssociatedObject_PreviewKeyDown(object sender, System.Windows.Input.KeyEventArgs e)
        {
            if (e.Key == System.Windows.Input.Key.OemPeriod || e.Key == System.Windows.Input.Key.Decimal)
            {
                var periodIndex = AssociatedObject.Text.IndexOf('.');
                if (periodIndex != -1)
                {
                    AssociatedObject.CaretIndex = (periodIndex + 1);
                    e.Handled = true;
                }
            }
        }
        #endregion

        #region Initialization
        public DecimalPlaceHotkeyBehavior()
            : base()
        {
        }
        #endregion
    }
}

أنا استخدمها على النحو التالي:

<TextBox xmlns:Behaviors="clr-namespace:GUI.Helpers.Behaviors" 
         xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity" 
         Text="{Binding Value, UpdateSourceTrigger=PropertyChanged, StringFormat={}{0:0.00}}">
        <i:Interaction.Behaviors>
            <Behaviors:DecimalPlaceHotkeyBehavior></Behaviors:DecimalPlaceHotkeyBehavior>
        </i:Interaction.Behaviors>
</TextBox>
Question

أحاول عرض عشري منسق في TextBox باستخدام ربط البيانات في WPF.

الأهداف

الهدف 1: عند تعيين خاصية عشرية في التعليمات البرمجية ، قم بعرض منزلتين عشريتين في TextBox.

الهدف 2: عندما يتفاعل المستخدم مع (أنواع) في TextBox ، لا تبويله.

الهدف 3: عمليات الربط يجب تحديث المصدر على PropertyChanged.

محاولات

المحاولة 1: لا يوجد تنسيق.

نحن هنا نبدأ تقريبا من الصفر.

<TextBox Text="{Binding Path=SomeDecimal, UpdateSourceTrigger=PropertyChanged}" />

انتهاك الهدف 1. SomeDecimal = 4.5 "4.50000" في TextBox.

المحاولة 2: استخدام StringFormat في Binding.

<TextBox Text="{Binding Path=SomeDecimal, UpdateSourceTrigger=PropertyChanged, StringFormat=F2}" />

ينتهك الهدف 2. قل SomeDecimal 2.5 ويتم عرض مربع نص "2.50". إذا اخترنا الكل واكتبنا "13.5" ، فنحن ننتهي بـ "13.5.00" في مربع النص لأن المنسق "مفيد" يقوم بإدراج الكسور العشرية والأصفار.

محاولة 3: استخدام MaskedTextBox الموسعة في WPF Toolkit.

http://wpftoolkit.codeplex.com/wikipage?title=MaskedTextBox

إذا افترضت أنني أقرأ الوثائق بشكل صحيح ، فإن القناع ## 0.00 يعني "رقمين اختياريين ، متبوعًا برقم مطلوب ، ونقطة عشرية ، واثنين آخرين من الأرقام المطلوبة. وهذا يجبرني على قول" أكبر عدد ممكن يمكن أن يدخل هذا textBox 999.99 "ولكن دعنا نقول أنا موافق على ذلك.

<xctk:MaskedTextBox Value="{Binding Path=SomeDecimal, UpdateSourceTrigger=PropertyChanged}" Mask="##0.00" />

ينتهك الهدف 2. يبدأ مربع النص بـ ___.__ وكتابة 5.75 عائدات 575.__ . الطريقة الوحيدة للحصول على 5.75 هي تحديد TextBox واكتب <space><space>5.75 .

المحاولة 4: استخدام spinner DecimalUpDown الموسعة في WPF Toolkit.

http://wpftoolkit.codeplex.com/wikipage?title=DecimalUpDown

<xctk:DecimalUpDown Value="{Binding Path=SomeDecimal, UpdateSourceTrigger=PropertyChanged}" FormatString="F2" />

انتهاك الهدف 3. DecimalUpDown لحسن الحظ يتجاهل UpdateSourceTrigger = PropertyChanged. يقترح أحد المنسقين في صفحة Codeplex Toolkit Toolkit الموسعة تعديل ControlTemplate على http://wpftoolkit.codeplex.com/discussions/352551/ . يفي هذا الهدف 3 ، ولكنه ينتهك الهدف 2 ، الذي يظهر نفس السلوك كما في محاولة 2.

المحاولة 5: استخدام نمط datatriggers ، استخدم التنسيق فقط إذا كان المستخدم لا يقوم بالتحرير.

ربط مزدوج مع StringFormat على TextBox

حتى إذا كان هذا الشخص راضيا عن الأهداف الثلاثة ، لا أريد استخدامه. (أ) تصبح مربعات النص 12 سطرًا بدلاً من 1 ، ويحتوي التطبيق الخاص بي على العديد من مربعات النص. (ب) تحتوي جميع مربعات النص الخاصة بي على سمة Style التي تشير إلى StaticResource عالمي يحدد الهامش والطول وأشياء أخرى. (C) ربما لاحظت أن الكود أدناه يحدد مسار الربط مرتين ، والذي ينتهك مبدأ DRY.

<TextBox>
    <TextBox.Style>
        <Style TargetType="{x:Type TextBox}">
            <Setter Property="Text" Value="{Binding Path=SomeDecimal, StringFormat=F2}" />
            <Style.Triggers>
                <Trigger Property="IsFocused" Value="True">
                    <Setter Property="Text" Value="{Binding Path=SomeDecimal, UpdateSourceTrigger=PropertyChanged}" />
                </Trigger>
            </Style.Triggers>
        </Style>
    </TextBox.Style>
</TextBox>

كل هذه الأشياء غير المريحة جانبا ...

ينتهك الهدف 2. أولا ، النقر على TextBox الذي يعرض "13.50" فجأة يجعله يعرض "13.5000" ، وهو أمر غير متوقع. ثانيًا ، إذا بدأت بـ "مربع نص" فارغًا ، وأكتب "13.50" ، سيحتوي مربع النص على "1350". لا أستطيع أن أشرح السبب ، ولكن لا يؤدي ضغط مفتاح الفترة إلى إدراج الأرقام العشرية إذا كان المؤشر في الطرف الأيمن من السلسلة في TextBox. إذا كان TextBox يحتوي على سلسلة ذات طول> 0 ، وأعد وضع المؤشر إلى أي مكان ما عدا النهاية اليمنى للسلسلة ، فيمكنني عندئذ إدراج النقاط العشرية.

المحاولة 6: افعلها بنفسي.

أنا على وشك الدخول في jouney من الألم والمعاناة ، إما عن طريق subclassing TextBox ، أو إنشاء خاصية المرفقة ، وكتابة رمز التنسيق بنفسي. ستكون مليئة بالتلاعب بالسلسلة ، وتسبب صدمات كبيرة.

هل لديها أي اقتراحات لتنسيق الكسور العشرية المرتبطة بصناديق النص التي تفي بجميع الأهداف المذكورة أعلاه؟






Related