在DP值改变后,启用并聚焦被禁用的控件

本文关键字:聚焦 控件 启用 DP 改变 | 更新日期: 2023-09-27 18:10:28

我有一个TextBox,只有在Counter >= 0时才必须启用。当Counter从-1变为0时,TextBox必须获得键盘焦点。

视图:

<Window x:Class="Thingy.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Thingy"
        mc:Ignorable="d"
        Title="Not random title" Height="200" Width="250">
    <Grid VerticalAlignment="Center" HorizontalAlignment="Center">
        <Grid.Resources>
            <local:IsNegativeConverter x:Key="IsNegativeConv"/>
            <Style x:Key="BoxStyle" TargetType="TextBox">
                <Style.Triggers>
                    <DataTrigger Binding="{Binding Counter, Converter={StaticResource IsNegativeConv}}" Value="True">
                        <!-- Here is the problem =( -->
                        <Setter Property="IsEnabled" Value="False"/> 
                    </DataTrigger>
                </Style.Triggers>
                <Setter Property="Width" Value="90"/>
            </Style>
        </Grid.Resources>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid Grid.Row="0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Label Grid.Column="0" Margin="2">Thingy</Label>
            <TextBox x:Name="ThingyBox" Grid.Column="1" Style="{StaticResource BoxStyle}"/>
        </Grid>
        <Grid Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Button Grid.Column="0" Content="-" Command="{Binding Decrease}" />
            <Label Grid.Column="1" Content="{Binding Counter}" Margin="2"/>
            <Button Grid.Column="2" Content="+" Command="{Binding Increase}" />
        </Grid>
    </Grid>
</Window>

后台代码:

public partial class MainWindow : Window
{
    public ViewModel ViewModel { get; private set; }
    public MainWindow()
    {
        ViewModel = new ViewModel();
        DataContext = ViewModel;
        ViewModel.OnCounterChanged += OnCounterChanged;
        InitializeComponent();
    }
    private void OnCounterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        if ((int)e.OldValue == -1 && (int)e.NewValue == 0)
            ThingyBox.Focus();
    }
}

ViewModel:

public class ViewModel : DependencyObject
{
    public event PropertyChangedCallback OnCounterChanged;
    public int Counter
    {
        get { return (int)GetValue(CounterProperty); }
        set { SetValue(CounterProperty, value); }
    }
    public static readonly DependencyProperty CounterProperty =
        DependencyProperty.Register("Counter", typeof(int), typeof(ViewModel), new PropertyMetadata(-2, CounterChanged));
    private static void CounterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        ViewModel vm = (ViewModel)d;
        if (vm.OnCounterChanged != null)
            vm.OnCounterChanged(d, e);
    }
    RelayCommand c_Increase;
    public ICommand Increase
    {
        get
        {
            if (c_Increase == null)
                c_Increase = new RelayCommand(p => this.IncreaseExecute(p), null);
            return c_Increase;
        }
    }
    private void IncreaseExecute(object parameter)
    {
        Counter++;
    }
    RelayCommand c_Decrease;
    public ICommand Decrease
    {
        get
        {
            if (c_Decrease == null)
                c_Decrease = new RelayCommand(p => this.DecreaseExecute(p), null);
            return c_Decrease;
        }
    }
    private void DecreaseExecute(object parameter)
    {
        Counter--;
    }
}

当计数器变为正或负时,代码启用和禁用控件,如果我注释DataTrigger,当计数器从0到1时,控件确实获得焦点。

它们单独工作正确,但它们不能同时工作。我猜DataTrigger触发得太晚了,但不知道为什么。

为什么DataTrigger执行得太晚?还是Focus()走得太快了?

我如何使它们都工作,如果可能的话,维护MVVM模型?

在DP值改变后,启用并聚焦被禁用的控件

使用IsEnabledChanged事件处理程序解决它:

<TextBox x:Name="ThingyBox" IsEnabledChanged="ThingyBox_IsEnabledChanged"/>
private void ThingyBox_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
{
    ((TextBox)sender).Focus();
}

如果有其他代理启用此ofc,它将不起作用,但对于当前场景有效=)