source

키를 누를 때 텍스트 상자 바인딩

factcode 2023. 4. 19. 23:32
반응형

키를 누를 때 텍스트 상자 바인딩

기본 데이터 바인딩TextBoxTwoWay그리고 그것은 다음 경우에만 그 텍스트를 자산에 커밋합니다.TextBox초점을 잃었어요

키를 눌렀을 때 데이터를 쉽게 바인딩할 수 있는 XAML 방법이 있나요?TextBox뒤에 있는 코드로 하는 것이 꽤 쉽다는 것을 알고 있습니다만, 만약 이것이TextBox어떤 콤플렉스 안에 있다DataTemplate.

부가 동작을 작성함으로써 순수 XAML 접근 방식을 만들 수 있습니다.

다음과 같은 경우:

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();
        }
    }
}

그런 다음 XAML에서 다음을 설정합니다.InputBindingsManager.UpdatePropertySourceWhenEnterPressedProperty키를 눌렀을 때 업데이트할 속성으로 이동합니다.이것처럼.

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

(XAML 파일의 루트 요소에 "b"에 대한 xmlns clr-namespace 참조를 포함하면 InputBindingsManager를 삽입하는 네임스페이스를 지정할 수 있습니다).

저는 이렇게 해서 이 문제를 해결했습니다.특수 이벤트 핸들러를 만들어 뒤에 있는 코드에 입력했습니다.

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(); }
    }
}

다음으로 XAML에 KeyUp 이벤트 핸들러로 추가했습니다.

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

이벤트 핸들러는 다음 명령을 사용합니다.sender자체 바인딩을 업데이트하기 위한 참조입니다.이벤트 핸들러는 독립형이기 때문에 복잡한 DataTemplate에서 작동합니다.이제 이 기능을 필요로 하는 모든 텍스트 상자에 이 이벤트 핸들러를 추가할 수 있습니다.

저는 당신이 설명한 것을 "순수한 XAML" 방식으로 실행할 수 있다고 생각하지 않습니다.UpdateSourceTrigger 속성을 다음과 같이 설정하여 텍스트 상자의 텍스트가 변경될 때마다(TextBox가 포커스를 잃었을 때가 아니라) 업데이트되도록 바인딩을 설정할 수 있습니다.

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

UpdateSourceTrigger를 "Explicit"로 설정하고 TextBox의 PreviewKeyDown 이벤트(Enter 키를 찾는 것)를 처리하면 원하는 것을 얻을 수 있지만 코드 배후에 있어야 합니다.아마 일종의 첨부 속성(EnterKeyTraversal 속성과 유사)이 당신에게 적합할 것입니다.

TextBox에서 상속되는 자체 컨트롤을 쉽게 만들어 프로젝트 전체에서 재사용할 수 있습니다.

다음과 같은 것이 동작합니다.

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();
            }
        }
    }
}

이 단계를 회피하는 방법이 있을 수 있지만 그렇지 않으면 다음과 같이 바인딩해야 합니다(Explicit 사용).

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

Ben과 ausadmin의 솔루션을 모두 조합하면 MVVM에 매우 편리한 솔루션이 됩니다.

<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.

ㅇㅇㅇㅇㅇ로 이어집니다.CommandDelegateCommand VM의 실장:

    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가상 머신에 있습니다.코드 가이드라인이 얼마나 엄격한지에 따라 달라집니다.

여기에서는 Attached Behaviour(유효한 솔루션이기도 한)를 추가하는 것보다 간단하고 쉬운 방법이 있습니다.기본 UpdateSourceTrigger(TextBox의 경우 LostFocus)를 사용하여 Enter 키에 InputBinding을 추가하여 명령어에 바인드합니다.

xaml은 다음과 같습니다.

       <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>

다음으로 Command 메서드는 다음과 같습니다.

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

TextBox는 속성에 바인딩되어 있습니다.

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

현재까지는 정상적으로 동작하고 있으며 TextBox에서 Enter Key 이벤트를 포착할 수 있습니다.

이것은 원래 질문에 대한 답변이 아니라 @Samuel Jack이 받아들인 답변의 연장선입니다.저는 다음과 같이 제 응용 프로그램을 실행했고, 사무엘의 솔루션의 우아함에 감탄했습니다.이것은 매우 깨끗하고 매우 재사용할 수 있습니다. 이는 단순히 제어 장치뿐만 아니라 모든 제어 장치에서도 사용할 수 있기 때문입니다.TextBox커뮤니티와 공유해야 한다고 생각했습니다.

1,의 TextBoxeson Enter를 것을 으로써 이 할 수 있습니다.Window Resources각 TextBox에 첨부하는 것이 아니라,물론 먼저 Samuel의 게시물에 따라 첨부된 행동을 실행해야 합니다.

<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>

「을의 자의 「 of Window」( 「Resources of the Window」)에 넣는 것으로, 할 수 .Grid대상 텍스트 상자를 포함합니다.

이것으로 충분합니다.

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

TextBox MultiBinding을 해야 .BindingOperations.GetMultiBindingExpression method를 합니다.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();
     }
}

내가 좋아하는 거의 모든 방법인 첨부 행동을 사용하여 꽤 우아하게 대답했습니다.

WPF Enter 키를 누른 후 텍스트 상자가 포커스를 잃도록 하는 방법

저는 개인적으로 마크업 연장을 하는 것이 더 깨끗한 접근법이라고 생각합니다.

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>

다른 솔루션(xaml은 사용하지 않지만 꽤 깨끗하다고 생각합니다).

class ReturnKeyTextBox : TextBox
{
    protected override void OnKeyUp(KeyEventArgs e)
    {
        base.OnKeyUp(e);
        if (e.Key == Key.Return)
            GetBindingExpression(TextProperty).UpdateSource();
    }
}

언급URL : https://stackoverflow.com/questions/563195/bind-textbox-on-enter-key-press

반응형