如何从 ViewModel 进行绑定

发布于 2024-12-17 21:41:44 字数 1189 浏览 6 评论 0原文

我正在尝试捕获在文本框中按下的 Enter 键,以便我可以启动对服务器的更新。它不起作用,所以我将问题简化为简单的元素。

在此示例中,绑定似乎不是在每次击键时发生,而是在稍后的某个时间发生。我需要在按下回车键时完成绑定。请考虑 VM 中的以下 XAML 和函数。

下面是文本框的 XAML

<TextBox Text="{Binding TextValue, Mode=TwoWay}" Height="23" Width="300">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="KeyDown">
            <cmd:EventToCommand Command="{Binding KeyDownCommand}"
                PassEventArgsToCommand="True" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</TextBox>

KeyDownCommand 按预期触发,但该值尚未出现在 TextValue 属性中。如果我第二次按 Enter 键,那么该值就在属性中吗?这是 KeyDown 命令。 ViewModel 的构造函数正确设置 keyDownCommand。

public RelayCommand<RoutedEventArgs> KeyDownCommand { get; private set; }
private void KeyDownAction(RoutedEventArgs eventArg)
{
    var source = eventArg.OriginalSource as FrameworkElement;
    var e = eventArg as KeyEventArgs;
    if (source != null && e != null && e.Key== Key.Enter)
    {
        e.Handled = true;
        MessageBox.Show(TextValue);
    }
}

看来我需要的是一种在按下 Enter 键时将 TextBox 的文本“发布”回 VM 的 TextValue 属性的方法。还是我还缺少其他东西。

I'm trying to capture the Enter key being pressed on a text box, so that I can kick off an update to the server. It's not working, and so I've reduced the problem to it's simplist elemetns.

In this example, it seems that the binding is not happening per keystroke, but at sometime later. I need to the binding to be completed by the time the enter key is pressed. Consider the following XAML and function from the VM.

Here's the XAML of the textbox

<TextBox Text="{Binding TextValue, Mode=TwoWay}" Height="23" Width="300">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="KeyDown">
            <cmd:EventToCommand Command="{Binding KeyDownCommand}"
                PassEventArgsToCommand="True" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</TextBox>

The KeyDownCommand fire as expected, howerver the value is not yet in the TextValue property. If I hit enter a second time then the value is in the property? Here's the KeyDownCommand. The constructor of the ViewModel sets the keyDownCommand correctly.

public RelayCommand<RoutedEventArgs> KeyDownCommand { get; private set; }
private void KeyDownAction(RoutedEventArgs eventArg)
{
    var source = eventArg.OriginalSource as FrameworkElement;
    var e = eventArg as KeyEventArgs;
    if (source != null && e != null && e.Key== Key.Enter)
    {
        e.Handled = true;
        MessageBox.Show(TextValue);
    }
}

It seems that what I need is a way to "post" the Text of the TextBox back to the TextValue property of the VM when the Enter key is pressed. Or is there something else I'm missing.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

ˉ厌 2024-12-24 21:41:44

尝试在绑定时将 UpdateSourceTrigger 设置为 PropertyChanged,如下所示:

<TextBox Text="{Binding TextValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Height="23" Width="300">

现在,每次更改文本时,视图模型属性都会更新。

更新:

对于 Silverlight,作为 UpdateSourceTrigger 的替代方案,您可以使用以下简单行为,在文本更改时更新绑定源:

public class TextChangedUpdateSourceBehavior : Behavior<TextBox>
{
    protected override void OnAttached()
    {
        base.OnAttached();

        AssociatedObject.TextChanged += OnTextChanged;
    }

    private void OnTextChanged(object sender, TextChangedEventArgs e)
    {
        var bindingExpression = AssociatedObject.GetBindingExpression(TextBox.TextProperty);

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

如下使用:

<TextBox Text="{Binding TextValue, Mode=TwoWay}" Height="23" Width="300">
    <i:Interaction.Behaviors>
        <b:TextChangedUpdateSourceBehavior />
    </i:Interaction.Behaviors>
</TextBox>

Try setting UpdateSourceTrigger to PropertyChanged on binding, like this:

<TextBox Text="{Binding TextValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Height="23" Width="300">

Now the view model property will be update every time the text is changed.

Update:

For Silverlight, as an alternative to UpdateSourceTrigger, you can use the following simple behavior that updates binding source whenever text changes:

public class TextChangedUpdateSourceBehavior : Behavior<TextBox>
{
    protected override void OnAttached()
    {
        base.OnAttached();

        AssociatedObject.TextChanged += OnTextChanged;
    }

    private void OnTextChanged(object sender, TextChangedEventArgs e)
    {
        var bindingExpression = AssociatedObject.GetBindingExpression(TextBox.TextProperty);

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

Use it like this:

<TextBox Text="{Binding TextValue, Mode=TwoWay}" Height="23" Width="300">
    <i:Interaction.Behaviors>
        <b:TextChangedUpdateSourceBehavior />
    </i:Interaction.Behaviors>
</TextBox>
云巢 2024-12-24 21:41:44

我刚发布问题,就找到了答案。

这是更正后的 KeyDownAction

private void KeyDownAction(RoutedEventArgs eventArg)
{
    var source = eventArg.OriginalSource as FrameworkElement;
    source.GetBindingExpression(TextBox.TextProperty).UpdateSource();
    var e = eventArg as KeyEventArgs;
    if (source != null && e != null && e.Key== Key.Enter)
    {
        e.Handled = true;
        MessageBox.Show(TextValue);
    }
}

现在,当我输入此内容时,我意识到我正在“打破”该模式,因为现在我的 ViewModel 对视图的了解更多了。

No sooner did I post the question, than I hit upon the answer.

Here's the corrected KeyDownAction

private void KeyDownAction(RoutedEventArgs eventArg)
{
    var source = eventArg.OriginalSource as FrameworkElement;
    source.GetBindingExpression(TextBox.TextProperty).UpdateSource();
    var e = eventArg as KeyEventArgs;
    if (source != null && e != null && e.Key== Key.Enter)
    {
        e.Handled = true;
        MessageBox.Show(TextValue);
    }
}

Of now as I type this I realize that I'm "breaking" the pattern, in as much as now my ViewModel knows more about the View that it should.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文