c# - 如何从 ViewModel 读取 TextBox 焦点 - MVVM Light

标签 c# wpf mvvm textbox mvvm-light

我有两个文本框,在我的 ViewModel 中我希望能够跟踪当前处于焦点的框。

<TextBox x:Name="textBox1" Text="Text Box 1"/>
<TextBox x:Name="textBox2" Text="Text Box 2"/>

如何从 ViewModel 中读取/识别当前处于焦点的文本框?

最佳答案

有多种方法可以实现这一目标,其中一些:

1)使用行为:

  • 您需要System.Windows.Interactivity.dll
  • 行为(设置 IsFocused 属性不会使元素聚焦,您需要稍微扩展行为才能实现此目的)

    public class FocusChangedBehavior : Behavior<UIElement>
    {
        public static readonly DependencyProperty IsFocusedProperty = 
           DependencyProperty.Register(
           nameof(IsFocused),
           typeof(bool),
           typeof(FocusChangedBehavior),
           new FrameworkPropertyMetadata(default(bool), 
                FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
    
        public bool IsFocused
        {
            get { return (bool)this.GetValue(IsFocusedProperty); }
            set { this.SetValue(IsFocusedProperty, value); }
        }
    
        /// <inheritdoc />
        protected override void OnAttached()
        {
            this.AssociatedObject.GotFocus += this.AssociatedObjectFocused;
            this.AssociatedObject.LostFocus += this.AssociatedObjectUnfocused;
        }
    
        /// <inheritdoc />
        protected override void OnDetaching()
        {
            this.AssociatedObject.GotFocus -= this.AssociatedObjectFocused;
            this.AssociatedObject.LostFocus -= this.AssociatedObjectUnfocused;
        }
    
        private void AssociatedObjectFocused(object sender, RoutedEventArgs e)
        {
            this.IsFocused = true;
        }
    
        private void AssociatedObjectUnfocused(object sender, RoutedEventArgs e)
        {
            this.IsFocused = false;
        }
    }
    
  • 在 XAML 中,您将 IsFocused 绑定(bind)到 ViewModel 中的属性。

    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"

    <TextBox x:Name="textBox1" Text="Text Box 1">
        <i:Interaction.Behaviors>
            <local:FocusChangedBehavior IsFocused="{Binding IsFocusedTxt1}" />
        </i:Interaction.Behaviors>
    </TextBox>
    
    <TextBox x:Name="textBox2" Text="Text Box 2">
        <i:Interaction.Behaviors>
            <local:FocusChangedBehavior IsFocused="{Binding IsFocusedTxt2}" />
        </i:Interaction.Behaviors>
    </TextBox>
    
  • 最后在 View 模型中创建属性

    public bool IsFocusedTxt1 { get; set; }
    
    public bool IsFocusedTxt2 { get; set; }
    



2) 或者,您可以在 XAML 中使用 EventTrigger

  • 您需要System.Windows.Interactivity.dllMicrosoftExpressionInteractions (For the ActionCommand)
  • 事件触发器:

    <TextBox x:Name="textBox1" Text="Text Box 1">
        <i:Interaction.Triggers>
            <i:EventTrigger  EventName="GotFocus">
                <i:InvokeCommandAction Command="{Binding NotifyFocusedReceivedTxt1Command}" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </TextBox>
    
  • 在 ViewModel 中创建命令 NotifyFocusedReceivedTxt1Command

    public ICommand NotifyFocusedReceivedTxt1Command { get; }
    
    // in constructor
    this.NotifyFocusedReceivedTxt1Command = new ActionCommand(this.FocusedReceivedTxt1);
    
    // and method
    private void FocusedReceivedTxt1()
    {
        // Your logic
    }
    
  • 此外,如果您不想引入许多命令/属性,您可以使用相同的命令并通过设置 CommandParameter 传递不同的文本框(稍微破坏 MVVM,但不是很严重)

    <TextBox x:Name="textBox1" Text="Text Box 1">
        <i:Interaction.Triggers>
            <i:EventTrigger  EventName="GotFocus">
                <i:InvokeCommandAction Command="{Binding NotifyFocusedReceivedCommand}" 
                                       CommandParameter="{Binding ., ElementName=textBox1}" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </TextBox>
    
    <TextBox x:Name="textBox2" Text="Text Box 2">
        <i:Interaction.Triggers>
            <i:EventTrigger  EventName="GotFocus">
                <i:InvokeCommandAction Command="{Binding NotifyFocusedReceivedCommand}" 
                                       CommandParameter="{Binding ., ElementName=textBox2}" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </TextBox>
    

    public ICommand NotifyFocusedReceivedCommand { get; }
    
    // in constructor
    this.NotifyFocusedReceivedCommand = new ActionCommand(this.FocusedReceived);
    
    // and method
    private void FocusedReceived(object control)
    {
        var txt = (TextBox)control;
        bool isFocused = txt.IsFocused;
        string name = txt.Name;
    }
    

关于c# - 如何从 ViewModel 读取 TextBox 焦点 - MVVM Light,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51918039/

相关文章:

c# - 你能得到 XslCompiledTransform 的进展吗?

c# - 当未选择行时,复选框列第一次不会更改其状态

mvvm - Flipview 不更新 SelectedItem

c# - 绑定(bind)MVVM模式中自定义元素的自定义事件

c# - ClickOnce 的替代品

c# - C# 中的自动设置属性

c# - 如果注册了 DispatcherUnhandledException,则 Control.LayoutUpdated 中发生异常后发生堆栈溢出

wpf - Storyboard未从 ControlTemplate DataTrigger 执行

wpf - 无法从样式的数据触发器更改 ContentControl 的模板 - 数据触发器未触发

c# - 如何处理 MVVM (WPF) 中的多个复选框?