是否有一个IValueConverter执行if-then

时间:2015-11-30 11:09:51

标签: c# wpf xaml

我要做的是:

<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 - 这会产生转化例外
  • 正在搜索here

3 个答案:

答案 0 :(得分:4)

不幸的是,if-then没有IValueConverter (更具体地说:你不能用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>

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

答案 1 :(得分:1)

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

如果您为此AlternationConverter指定了两个值,并且您能够将EditEnabled属性提供为整数01,那么您可以将01映射到您想要的任何值。

如果您觉得将bool转换为整数(我可以同情的话)是没有意义的,您仍然可以使用AlternationConverter作为自定义转换器的灵感来源不要求模型值为int类型。

答案 2 :(得分:1)

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

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}" />