在DP更改值后启用并聚焦禁用的控件

时间:2015-08-30 11:32:51

标签: c# wpf

我有一个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();
    }
}

视图模型:

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模型?

1 个答案:

答案 0 :(得分:2)

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

<TextBox x:Name="ThingyBox" IsEnabledChanged="ThingyBox_IsEnabledChanged"/>

private void ThingyBox_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
{
    ((TextBox)sender).Focus();
}

如果有其他代理启用此ofc,它将无法正常工作,但对于当前场景的工作原理=)