繁体   English   中英

WPF 显示使用 DataTrigger 的控制在 TabOrder 中跳过它

[英]WPF showing control with DataTrigger skips it in TabOrder

当前一个TextBox的值不是 0.00(零)时,我想显示“其他详细信息”文本框。 这可以通过 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"/>

但是,问题是,当将FirstTB的值更改为 <> 0 并按Tab时,焦点会跳转到ThirdTB而不是SecondTB (即使由于 DataTrigger, SecondTB现在是可见的)。 我该如何解决这个问题?


可悲的是, UpdateSourceTrigger=PropertyChanged似乎不是一个选项,因为它会干扰StringFormat s - 当您编辑值时它会提供糟糕的用户体验,由于不断的 StringFormat 评估,carret 会疯狂地跳来跳去。 上面示例中使用的 Viewmodel:

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)));
        }
    }

}

也许是一个愚蠢的工作。 但这将完成工作:

看法:

<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;
}

如果您使用IValueConverter ,您将获得一种非常优雅的方式来解决您的问题。 每次更改值时,都会调用逻辑。


public class IsZeroToHiddenConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is double d && d == 0)
            return Visibility.Hidden;
        return Visibility.Visible;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

您还可以尝试并添加ConverterParameter来决定是否需要CollapsedHidden行为。

用法


<Grid>
    <Grid.Resources>
        <local:IsZeroToHiddenConverter x:Key="IsZeroToHiddenConverter"/>
    </Grid.Resources>
    <Grid VerticalAlignment="Center" HorizontalAlignment="Center">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <TextBox x:Name="Tb1" Grid.Row="0" Width="100" Margin="5" Text="{Binding Path=Amount, StringFormat=F2, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
        <TextBox x:Name="Tb2" Grid.Row="1" Width="100" Margin="5" Visibility="{Binding Path=Amount, Converter={StaticResource IsZeroToHiddenConverter}}"/>
        <TextBox x:Name="Tb3" Grid.Row="2" Width="100" Margin="5"/>
    </Grid>
</Grid>

预习

在此处输入图像描述

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM