是否有一个IValueConverter可以执行if-then

本文关键字:执行 if-then 有一个 IValueConverter 是否 | 更新日期: 2023-09-27 18:25:05

我要做的事情:

<Grid>
  <Grid.RowDefinitions>
    ...
    <!--The next line is pseudo code for what I am trying to achieve-->
    <RowDefintion Height="if(EditEnabled) { 10* } else { 0 }" />
    ...
  </Grid.RowDefinition>
  ...
  <DockPanel Visibility="{Binding EditEnabled, Converter={StaticResource InverseBooleanToVisibilityConverter}}" ...>
  ...

我试图根据是否启用编辑来更改DockPanel的可见性,同时保持调整大小和固定高度和相对高度的能力。

问题:

有没有一个IValueConverterSystem.Windows.Data.IValueConverter)可以接受一个布尔值和两个数字,并根据布尔值选择其中一个GridLength?从检查IValueConverter的接口来看,这似乎不是一个合适的类型。

或者有更好的方法来注入我想要的GridLength吗?

我尝试过的:

  • 浏览IValueConverter的继承者-对我来说没有什么明显的
  • Height="10*"移动到DockPanel标记内,并将RowDefinition更改为Auto,这创建了一个转换异常
  • 在此处搜索

是否有一个IValueConverter可以执行if-then

不幸的是,没有IValueConverter可以执行if-then
(更具体地说:您不能使用XAML执行if-then逻辑)
但是您可以在C#代码中执行if-then逻辑
这是的解决方案

public class HeightConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        bool enableEdit = (bool)value;
        double param = System.Convert.ToDouble(parameter);
        if (enableEdit)
            return new GridLength(param, GridUnitType.Star);
        else
            return new GridLength(0);
    }
    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

窗户是这样的。

<Window.Resources>
    <local:HeightConverter x:Key="heightConverter"/>
    <sys:Int32 x:Key="param">10</sys:Int32>
</Window.Resources>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="{Binding Path=EditEnabled, Converter={StaticResource heightConverter}, ConverterParameter={StaticResource param}}" />
    </Grid.RowDefinitions>
</Grid>

还请考虑定义您将要使用的必需命名空间,如以下

xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:local="clr-namespace:[your namespace]"

更新使用IMutliValueConverter 可以获得相同的结果

public class HeightMultiConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        bool enableEdit = (bool)values[0];
        double param = System.Convert.ToDouble(values[1]);
        if (enableEdit)
            return new GridLength(param, GridUnitType.Star);
        else
            return new GridLength(0);
    }
    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

和像这样的窗口

<Window.Resources>
    <local:HeightMultiConverter x:Key="heightMutliConverter"/>
    <sys:Int32 x:Key="param">10</sys:Int32>
</Window.Resources>
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition >
            <RowDefinition.Height>
                <MultiBinding Converter="{StaticResource heightMutliConverter}">
                    <Binding Path="EditEnabled"/>
                    <Binding Source="{StaticResource param}"/>
                </MultiBinding>
            </RowDefinition.Height>
        </RowDefinition>
    </Grid.RowDefinitions>
</Grid>

注意:不要忘记,您必须通过设置DataContext属性来处理Source

您可以使用内置转换器:AlternationConverter。指定一个值列表(任意类型),绑定到一个整数,转换器在值列表中查找该整数(以值计数为模)。

如果为此AlternationConverter指定两个值,并且能够将EditEnabled属性提供为整数01,则可以将该01映射到所需的任何值。

如果您觉得先将bool转换为整数没有意义(我对此表示赞同),您仍然可以使用AlternationConverter作为定制转换器的灵感,该转换器不需要模型值为int类型。

如中所述创建BooleanConverter<T>基类http://stackoverflow.com/a/5182660/469708

public class BooleanConverter<T> : IValueConverter
{
    public BooleanConverter(T trueValue, T falseValue)
    {
        True = trueValue;
        False = falseValue;
    }
    public T True { get; set; }
    public T False { get; set; }
    public virtual object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value is bool && ((bool) value) ? True : False;
    }
    public virtual object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value is T && EqualityComparer<T>.Default.Equals((T) value, True);
    }
}

然后写入

public class BooleanToGridLengthConverter : BooleanConverter<System.Windows.GridLength>
{
   public BooleanToGridLengthConverter() : base(
     new System.Windows.GridLength(1, System.Windows.GridUnitType.Star),
     new System.Windows.GridLength(0))
   {
   }
}

true和false的值可以直接设置,不需要MultiValueConverter(只要只有布尔参数需要可绑定即可)。

<convert:BooleanToGridLengthConverter x:Key="Converter" True="10*" False="0" />

或者,您可以从MarkupExtension派生转换器,并直接使用它,如下所示:

<RowDefinition Height="{Binding EditEnabled, Converter={convert:BooleanToGridLengthConverter True=10*, False=0}" />