wpfxamldatatriggertab-ordering

WPF showing control with DataTrigger skips it in TabOrder


I would like to show 'additional details' Textbox when the previous TextBox's value is not 0.00 (zero). This is easily accomplished with DataTriggers:

<TextBox Name="FirstTB" Text="{Binding Amount, StringFormat=F2}"/><!--when this TB is not 0-->
<TextBox Name="SecondTB"> <!--show this TB-->
    <TextBox.Style>
        <Style TargetType="{x:Type TextBox}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Amount}" Value="0">
                    <Setter Property="Visibility" Value="Hidden"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </TextBox.Style>
</TextBox>
<TextBox Name="ThirdTB"/>

The issue is, however, when changing value of FirstTB to <> 0 and pressing Tab the focus jumps to the ThirdTB instead of SecondTB (even though SecondTB now is Visible due to the DataTrigger). How can I fix this issue?


Sadly, UpdateSourceTrigger=PropertyChanged does not appear to be an option due to its interference with StringFormats - it gives terrible UX when you are editing the value, carret jumps around like crazy due to constant StringFormat evaluation. Viewmodel used in example above:

public class MyVM : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    private double _amount;
    public double Amount
    {
        get { return _amount; }
        set
        {
            _amount = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Amount)));
        }
    }

}

Solution

  • Maybe a stupid work around. But this will do the work:

    View:

    <TextBox Name="SecondTB" IsVisibleChanged="SecondTB_OnIsVisibleChanged">
         <!--show this TB-->
         <TextBox.Style>
             <Style TargetType="{x:Type TextBox}">
                  <Style.Triggers>
                        <DataTrigger Binding="{Binding Amount, Mode=OneWay}" Value="0">
                             <Setter Property="Visibility" Value="Collapsed"/>
                        </DataTrigger>
                  </Style.Triggers>
             </Style>
        </TextBox.Style>
    </TextBox>
    

    C#:

    private void SecondTB_OnIsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        if (((bool) e.NewValue))
        {
            if(!(sender is TextBox txbx)) return;
            ThirdTB.GotFocus += ThirdTbOnGotFocus;
        }
    }
    
    private void ThirdTbOnGotFocus(object sender, RoutedEventArgs e)
    {
        SecondTB.Focus();
        ThirdTB.GotFocus -= ThirdTbOnGotFocus;
    }