এন্টার-কী টিপে টেক্সটবক্সকে বাঁধুন


108

ডিফল্ট ডেটাবাইন্ডিংটি চালু TextBoxথাকে TwoWayএবং এটি যখন TextBoxতার ফোকাসটি হারিয়ে যায় তখনই এটি পাঠ্যের প্রতিশ্রুতি দেয় ।

আমি যখন Enterকী টিপছি তখন ডেটাবাইন্ডিংয়ের কোনও সহজ এক্সএএমএল উপায় আছে TextBox? আমি জানি পিছনের কোডটি করা বেশ সহজ, তবে ভেবে দেখুন এটি যদি TextBoxকিছু জটিল ভিতরে থাকে DataTemplate

উত্তর:


137

সংযুক্ত আচরণ তৈরি করে আপনি নিজেকে খাঁটি এক্সএএমএল পদ্ধতির তৈরি করতে পারেন ।

এটার মতো কিছু:

public static class InputBindingsManager
{

    public static readonly DependencyProperty UpdatePropertySourceWhenEnterPressedProperty = DependencyProperty.RegisterAttached(
            "UpdatePropertySourceWhenEnterPressed", typeof(DependencyProperty), typeof(InputBindingsManager), new PropertyMetadata(null, OnUpdatePropertySourceWhenEnterPressedPropertyChanged));

    static InputBindingsManager()
    {

    }

    public static void SetUpdatePropertySourceWhenEnterPressed(DependencyObject dp, DependencyProperty value)
    {
        dp.SetValue(UpdatePropertySourceWhenEnterPressedProperty, value);
    }

    public static DependencyProperty GetUpdatePropertySourceWhenEnterPressed(DependencyObject dp)
    {
        return (DependencyProperty)dp.GetValue(UpdatePropertySourceWhenEnterPressedProperty);
    }

    private static void OnUpdatePropertySourceWhenEnterPressedPropertyChanged(DependencyObject dp, DependencyPropertyChangedEventArgs e)
    {
        UIElement element = dp as UIElement;

        if (element == null)
        {
            return;
        }

        if (e.OldValue != null)
        {
            element.PreviewKeyDown -= HandlePreviewKeyDown;
        }

        if (e.NewValue != null)
        {
            element.PreviewKeyDown += new KeyEventHandler(HandlePreviewKeyDown);
        }
    }

    static void HandlePreviewKeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Enter)
        {
            DoUpdateSource(e.Source);
        }
    }

    static void DoUpdateSource(object source)
    {
        DependencyProperty property =
            GetUpdatePropertySourceWhenEnterPressed(source as DependencyObject);

        if (property == null)
        {
            return;
        }

        UIElement elt = source as UIElement;

        if (elt == null)
        {
            return;
        }

        BindingExpression binding = BindingOperations.GetBindingExpression(elt, property);

        if (binding != null)
        {
            binding.UpdateSource();
        }
    }
}

তারপরে আপনার এক্সএএমএল-এ আপনি কীটি চাপলে InputBindingsManager.UpdatePropertySourceWhenEnterPressedPropertyআপডেট করতে চান এমনটিতে সম্পত্তি সেট করে Enter। এটার মত

<TextBox Name="itemNameTextBox"
         Text="{Binding Path=ItemName, UpdateSourceTrigger=PropertyChanged}"
         b:InputBindingsManager.UpdatePropertySourceWhenEnterPressed="TextBox.Text"/>

(আপনাকে কেবল আপনার এক্সএএমএল ফাইলের মূল উপাদানটিতে "বি" এর জন্য একটি এক্সএমএলএনএস সিএলআর-নেমস্পেসের রেফারেন্স অন্তর্ভুক্ত করে নিশ্চিত করতে হবে যে আপনি ইনপুটবাইন্ডিংস ম্যানেজারটি কখনই রেখেছেন to


11
ভবিষ্যতের পাঠকদের কয়েক মিনিটের বেঁচে থাকার সংরক্ষণের প্রয়াসে, আমি এটি কেবলমাত্র আমার প্রকল্পে ব্যবহার করেছি এবং উপরে প্রদত্ত নমুনা এক্সএএমএল সঠিকভাবে কাজ করে নি। উত্সটি প্রতিটি চরিত্র পরিবর্তনের উপর আপডেট হয়েছিল। "আপডেটসোর্সটি ট্রিগার = প্রপার্টিচেন্জড" পরিবর্তন করে "আপডেটসোর্সটি ট্রিগার = স্পষ্টিকাল" এ সমস্যার সমাধান হয়েছে। এখন এটি সমস্ত কাঙ্ক্ষিত হিসাবে কাজ করে।
ইহাকে

1
@ আইহাক: আমি মনে করি আপনার প্রস্তাবিত পরিবর্তনটি যদিও হারিয়ে ফোকাসের উপর আপডেট হওয়া প্রতিরোধ করবে
ভোটকফি

4
আপডেটসোর্সট্রিগার = প্রপার্টি চেঞ্জ করা কোনও আসল নম্বর টাইপ করার সময় অসুবিধা হতে পারে। উদাহরণস্বরূপ "3." একটি ভাসা আবদ্ধ যখন একটি সমস্যার কারণ। আমি সংযুক্ত আচরণের পাশাপাশি আপডেটসোর্স ট্রিগ্রার (বা লস্টফোকাসে সেট করা) নির্দিষ্ট না করার পরামর্শ দেব। এটি উভয় বিশ্বের সেরা দেয়।
ডেভিড হলিনহেড

2
চমৎকার কাজ! ক্ষুদ্র নাইট-পিক: যখন UpdatePropertySourceWhenEnterPressedকোনও বৈধ মান থেকে অন্য বৈধ মানতে পরিবর্তন হয় আপনি PreviewKeyDownঅকারণে ইভেন্টটি সাবস্ক্রাইব ও পুনরায় সাবস্ক্রাইব করছেন । পরিবর্তে, আপনার প্রয়োজন হবে কিনা চেক করা হল e.NewValueহয় nullবা না। তা না হলে nullসাবস্ক্রাইব করুন; অন্যথায়, যদি null, তবে সাবস্ক্রাইব করুন।
নিকোলাস মিলার

1
আমি এই সমাধানটি ভালোবাসি, এটি পোস্ট করার জন্য ধন্যবাদ! যার জন্য আপনার আবেদনে অসংখ্য পাঠ্যবক্সগুলিতে এই আচরণটি সংযুক্ত করা দরকার, আপনি কীভাবে খুব সহজেই তা অর্জন করতে পারেন সে সম্পর্কে আমি এই উত্তরে একটি এক্সটেনশান পোস্ট করেছি। পোস্টটি এখানে দেখুন
নিক

50

এইভাবেই আমি এই সমস্যার সমাধান করেছি। আমি একটি বিশেষ ইভেন্ট হ্যান্ডলার তৈরি করেছি যা পিছনে কোডটিতে চলে গেছে:

private void TextBox_KeyEnterUpdate(object sender, KeyEventArgs e)
{
    if (e.Key == Key.Enter)
    {
        TextBox tBox = (TextBox)sender;
        DependencyProperty prop = TextBox.TextProperty;

        BindingExpression binding = BindingOperations.GetBindingExpression(tBox, prop);
        if (binding != null) { binding.UpdateSource(); }
    }
}

তারপরে আমি কেবল এক্সএএমএল-তে এটি একটি কীআপ ইভেন্ট হ্যান্ডলার হিসাবে যুক্ত করেছি:

<TextBox Text="{Binding TextValue1}" KeyUp="TextBox_KeyEnterUpdate" />
<TextBox Text="{Binding TextValue2}" KeyUp="TextBox_KeyEnterUpdate" />

ইভেন্ট হ্যান্ডলারটি নিজের senderরেফারেন্সটি আপডেট হওয়ার জন্য এটির নিজস্ব রেফারেন্স ব্যবহার করে uses যেহেতু ইভেন্ট হ্যান্ডলারটি স্বয়ংসম্পূর্ণ তাই এটি একটি জটিল ডাটাটেম্প্লেটে কাজ করা উচিত। এই বৈশিষ্ট্যটির প্রয়োজন এমন সমস্ত পাঠ্যবক্সগুলিতে এই ইভেন্ট ইভেন্ট হ্যান্ডলারটি যুক্ত করা যেতে পারে।


8
কিছু আমাকে বলছে এটি একটি আন্ডাররেটেড পোস্ট। অনেকগুলি উত্তর জনপ্রিয় কারণ সেগুলি "এক্সএএমএল-ওয়াই"। তবে এটি বেশিরভাগ ক্ষেত্রে স্থান সংরক্ষণ করে।
j রিভ

3
+1 এটি আপনাকে আপডেটসোর্সটি ট্রিগারকে একা ছাড়ার অনুমতি দেয় যদি আপনি ইতিমধ্যে কঠোরভাবে আপনার পাঠ্যবক্সের বাইন্ডিংগুলি আপনার পছন্দ মতো আচরণ করতে পারেন (শৈলী, বৈধতা, দ্বি ইত্যাদি), তবে বর্তমানে কেবল এন্টার টিপানোর পরে ইনপুট পাবেন না ।
জামিন

2
এটি আমি খুঁজে পেয়েছি এমন সবচেয়ে পরিষ্কার পদ্ধতি এবং আমার মতে উত্তর হিসাবে চিহ্নিত করা উচিত। উত্স বৈশিষ্ট্য আপডেট করার পরে টেক্সটবক্স থেকে ফোকাস অপসারণ করতে প্রেরককে একটি অতিরিক্ত নাল চেক, কী (রিটার্ন (আমার কীবোর্ডে কী লিখুন পুনরায় ফিরে আসে) এবং কীবোর্ড.ক্লেয়ারফোকাস () এ একটি চেক যুক্ত করা হয়েছে। পিয়ার পর্যালোচনার অপেক্ষার উত্তরে আমি সম্পাদনা করেছি।
ওস্টিন

2
উপরের মন্তব্যে একমত তবে আমার জন্য কীডাউন ইভেন্টটি আরও উপযুক্ত ছিল
অ্যালেন্ডার

1
আমি KeyBindingএক্সএএমএল-তে এই পদ্ধতিটি চালিত করতে ব্যবহার করেছি কারণ আমার ইউআইতে একটি "ডিফল্ট" নিয়ন্ত্রণ রয়েছে যা প্রবেশ কীটি ধরে ches ইউআই গাছটিকে "ডিফল্ট" নিয়ন্ত্রণে প্রচার করা বন্ধ করতে আপনাকে এই পাঠ্যবক্সের মধ্যে এটি ধরতে হবে।
সিএডি 11:58

46

আমি বিশ্বাস করি না যে আপনি যা বর্ণনা করছেন তা করার কোনও "খাঁটি এক্সএএমএল" উপায় আছে। আপনি একটি বাঁধাই সেট আপ করতে পারেন যাতে আপডেটসোর্স ট্রাইগার বৈশিষ্ট্যটি সেট করে যেমন পাঠ্যবক্সের পাঠ্য পরিবর্তিত হয় (যখন টেক্সটবক্স ফোকাস হারায় তখন পরিবর্তে) এটি আপডেট হয় :

<TextBox Name="itemNameTextBox"
    Text="{Binding Path=ItemName, UpdateSourceTrigger=PropertyChanged}" />

আপনি যদি আপডেটসোর্সটি ট্রিগারটিকে "স্পষ্টিত" হিসাবে সেট করে থাকেন এবং তারপরে টেক্সটবক্সের প্রিভিউকি কীডাউন ইভেন্টটি পরিচালনা করেন (এন্টার কীটি সন্ধান করছেন) তবে আপনি যা চান তা অর্জন করতে পারেন তবে এতে কোড-পিছনের প্রয়োজন হবে। সম্ভবত আপনার জন্য কোনও ধরণের সংযুক্ত সম্পত্তি (আমার এন্টারকি ট্র্যাভারসাল সম্পত্তির সমান) ওয়াল্ড ওয়ার্ক।


3
উত্তর হিসাবে চিহ্নিত হিসাবে উত্তরটি সহজ হতে পারে তবে এর কিছু সীমাবদ্ধতা রয়েছে। যে চিত্রটি আপনি আবদ্ধ সম্পত্তিটির সেট-ফাংশনটিতে কোনও ধরণের চেক করতে চান (ইনপুটটি বৈধ কিনা তা পরীক্ষা করে)। আপনি যে চেক ফাংশনটি ব্যবহারকারীর দ্বারা চাপানো প্রতিটি কী-এর পরে কল করতে চান না, আপনি কি (বিশেষত যখন ফাংশনটি কিছুটা সময় নেয় না)?
sth_Weird

25

আপনি টেক্সটবক্স থেকে উত্তরাধিকার সূত্রে নিজের কন্ট্রোলটি সহজেই তৈরি করতে পারেন এবং আপনার পুরো প্রকল্পে এটি পুনরায় ব্যবহার করতে পারেন।

এর মতো কিছু কাজ করা উচিত:

public class SubmitTextBox : TextBox
{
    public SubmitTextBox()
        : base()
    {
        PreviewKeyDown += new KeyEventHandler(SubmitTextBox_PreviewKeyDown);
    }

    void SubmitTextBox_PreviewKeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Enter)
        {
            BindingExpression be = GetBindingExpression(TextBox.TextProperty);
            if (be != null)
            {
                be.UpdateSource();
            }
        }
    }
}

এই পদক্ষেপটি ঘুরে দেখার কোনও উপায় থাকতে পারে তবে অন্যথায় আপনার এটির মতো আবদ্ধ হওয়া উচিত (স্পষ্ট করে ব্যবহার করে):

<custom:SubmitTextBox
    Text="{Binding Path=BoundProperty, UpdateSourceTrigger=Explicit}" />

9
ডাব্লুপিএফ / সিলভারলাইটে আপনার কখনই উত্তরাধিকার ব্যবহার করা উচিত নয় - এটি স্টাইলগুলি মিস করে এবং সংযুক্ত আচরণগুলির মতো নমনীয় নয়। উদাহরণস্বরূপ সংযুক্ত আচরণগুলির সাথে আপনার একই পাঠ্যবক্সে ওয়াটারমার্ক এবং আপডেটঅনএন্ট্টার উভয়ই থাকতে পারে।
মিখাইল

14

আপনি যদি বেন এবং অ্যাসাদমিনের উভয় সমাধানকে একত্রিত করেন তবে আপনি খুব এমভিভিএম বন্ধুত্বপূর্ণ সমাধানটি শেষ করবেন:

<TextBox Text="{Binding Txt1, Mode=TwoWay, UpdateSourceTrigger=Explicit}">
    <TextBox.InputBindings>
        <KeyBinding Gesture="Enter" 
                    Command="{Binding UpdateTextBoxBindingOnEnterCommand}"
                    CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type TextBox}}}" />
    </TextBox.InputBindings>
</TextBox>

... যার অর্থ আপনি TextBoxনিজেকে প্যারামিটার হিসাবে পাস করছেন Command

এটি আপনার চেহারাটির দিকে নিয়ে যায় Command(যদি আপনি DelegateCommandনিজের ভিএম-এ স্টাইল প্রয়োগ করে থাকেন):

    public bool CanExecuteUpdateTextBoxBindingOnEnterCommand(object parameter)
    {
        return true;
    }

    public void ExecuteUpdateTextBoxBindingOnEnterCommand(object parameter)
    {
        TextBox tBox = parameter as TextBox;
        if (tBox != null)
        {
            DependencyProperty prop = TextBox.TextProperty;
            BindingExpression binding = BindingOperations.GetBindingExpression(tBox, prop);
            if (binding != null) 
                binding.UpdateSource();
        }
    }

এই Commandবাস্তবায়ন TextBoxকোড-পিছনের কোনও কোডের যে কোনও এবং সর্বোত্তমর জন্য ব্যবহার করা যেতে পারে যদিও আপনি এটি নিজের শ্রেণিতে রাখতে চাইতে পারেন যাতে System.Windows.Controlsআপনার ভিএম- তে কোনও নির্ভরতা নেই । এটি আপনার কোড নির্দেশিকা কত কঠোর তার উপর নির্ভর করে।


খুশী হলাম। খুব পরিষ্কার. যদি কোনও মাল্টবাইন্ডিং জড়িত থাকে তবে আপনাকে বাইন্ডিংইপেশনগুলি ব্যবহার করতে হবে need গেটবাইন্ডিং এক্সপ্রেশনবেস (টিবক্স, প্রপ); এবং তারপরে বাঁধাই করা হবে pউক্ত আপডেট ();
ভোটকফি

4

এখানে এমন একটি পদ্ধতির কথা যা আমার কাছে বেশ সোজা মনে হয় এবং এটি একটি অ্যাচটেডবিহাভিওর যুক্ত করা সহজ (যা একটি বৈধ সমাধানও)। আমরা ডিফল্ট আপডেটসোর্স ট্রাইগার (টেক্সটবক্সের জন্য লস্টফোকাস) ব্যবহার করি এবং তারপরে একটি কমান্ডের সাথে আবদ্ধ এন্টার কীতে একটি ইনপুটবাইন্ডিং যুক্ত করি।

এক্সামলটি নিম্নরূপ

       <TextBox Grid.Row="0" Text="{Binding Txt1}" Height="30" Width="150">
        <TextBox.InputBindings>
            <KeyBinding Gesture="Enter" 
                        Command="{Binding UpdateText1Command}"
                        CommandParameter="{Binding RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type TextBox}},Path=Text}" />
        </TextBox.InputBindings>
    </TextBox>

তারপরে কমান্ডের পদ্ধতিগুলি

Private Function CanExecuteUpdateText1(ByVal param As Object) As Boolean
    Return True
End Function
Private Sub ExecuteUpdateText1(ByVal param As Object)

    If TypeOf param Is String Then
        Txt1 = CType(param, String)
    End If
End Sub

এবং পাঠ্যবক্সটি সম্পত্তিতে আবদ্ধ

 Public Property Txt1 As String
    Get
        Return _txt1
    End Get
    Set(value As String)
        _txt1 = value
        OnPropertyChanged("Txt1")
    End Set
End Property

এখনও অবধি এটি ভালভাবে কাজ করছে বলে মনে হচ্ছে এবং টেক্সটবক্সে প্রবেশ কী ইভেন্টটি ক্যাচ করে।


4

এটি মূল প্রশ্নের উত্তর নয়, বরং @ সামুয়েল জ্যাকের গৃহীত উত্তরের একটি বর্ধন । আমি আমার নিজের প্রয়োগটিতে নিম্নলিখিতগুলি করেছি এবং শমূয়েলের সমাধানের কৌতুক দেখে অবাক হয়েছি। এটি খুব পরিষ্কার এবং খুব পুনরায় ব্যবহারযোগ্য, কারণ এটি কোনও নিয়ন্ত্রণে ব্যবহার করা যেতে পারে, কেবল এটিই নয় TextBox। আমি ভেবেছিলাম এটি সম্প্রদায়ের সাথে ভাগ করে নেওয়া উচিত।

আপনার যদি এমন হাজার সহ উইন্ডো থাকে TextBoxesযা সকলকে এন্টারে বাইন্ডিং উত্স আপডেট করার প্রয়োজন হয় Window Resourcesতবে আপনি প্রতিটি টেক্সটবক্সের সাথে সংযুক্তি না করে নীচের এক্সএএমএলকে অন্তর্ভুক্ত করে তাদের সবার সাথে এই আচরণটি সংযুক্ত করতে পারেন । প্রথমে অবশ্যই অবশ্যই শমূয়েলের পোস্ট অনুসারে সংযুক্ত আচরণটি বাস্তবায়ন করতে হবে ।

<Window.Resources>
    <Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
        <Style.Setters>
            <Setter Property="b:InputBindingsManager.UpdatePropertySourceWhenEnterPressed" Value="TextBox.Text"/>
        </Style.Setters>
    </Style>
</Window.Resources>

উইন্ডোর শিশু উপাদানগুলির একটিতে (যেমন ক Grid) লক্ষ্যযুক্ত পাঠ্যবক্সগুলিকে অন্তর্ভুক্ত করে স্টাইলটি সৃজন করে আপনি প্রয়োজনের ক্ষেত্রে সর্বদা সুযোগ সীমাবদ্ধ করতে পারেন ।


2

আপনি যদি আপনার টেক্সটবক্সের সাথে মাল্টিবাইন্ডিং ব্যবহার করছেন তবে আপনার BindingOperations.GetMultiBindingExpressionপরিবর্তে পদ্ধতিটি ব্যবহার করা দরকার BindingOperations.GetBindingExpression

// Get the correct binding expression based on type of binding
//(simple binding or multi binding.
BindingExpressionBase binding = 
  BindingOperations.GetBindingExpression(element, prop);
if (binding == null)
{
    binding = BindingOperations.GetMultiBindingExpression(element, prop);
}

if (binding != null)
{
     object value = element.GetValue(prop);
     if (string.IsNullOrEmpty(value.ToString()) == true)
     {
         binding.UpdateTarget();
     }
     else
     {
          binding.UpdateSource();
     }
}

1

এটি আমার পক্ষে কাজ করে:

        <TextBox                 
            Text="{Binding Path=UserInput, UpdateSourceTrigger=PropertyChanged}">
            <TextBox.InputBindings>
                <KeyBinding Key="Return" 
                            Command="{Binding Ok}"/>
            </TextBox.InputBindings>
        </TextBox>

1

সংযুক্ত আচরণগুলি, প্রায় কোনও কিছুর জন্য আমার পছন্দের পদ্ধতিটি ব্যবহার করে এখানে বেশ মার্জিতভাবে উত্তর দেওয়া হয়েছে।

প্রবেশের পরে পাঠ্যবাক্সটি কীভাবে ফোকাস হারাবে ডাব্লুপিএফ


0

আমি ব্যক্তিগতভাবে মনে করি একটি মার্কআপ এক্সটেনশন হওয়া একটি পরিষ্কার পদ্ধতির er

public class UpdatePropertySourceWhenEnterPressedExtension : MarkupExtension
{
    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return new DelegateCommand<TextBox>(textbox => textbox.GetBindingExpression(TextBox.TextProperty).UpdateSource());
    }
}


<TextBox x:Name="TextBox"
             Text="{Binding Text}">
        <TextBox.InputBindings>
            <KeyBinding Key="Enter"
                        Command="{markupExtensions:UpdatePropertySourceWhenEnterPressed}" 
                        CommandParameter="{Binding ElementName=TextBox}"/>
        </TextBox.InputBindings>
</TextBox>

0

একটি আলাদা সমাধান (এক্সএএমএল ব্যবহার না করা তবে এখনও আমার মনে হয় বেশ পরিষ্কার)।

class ReturnKeyTextBox : TextBox
{
    protected override void OnKeyUp(KeyEventArgs e)
    {
        base.OnKeyUp(e);
        if (e.Key == Key.Return)
            GetBindingExpression(TextProperty).UpdateSource();
    }
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.