为什么绑定不起作用?

时间:2012-12-19 12:44:57

标签: c# wpf binding user-controls

所以我创建了一个带有“ShowCode”属性的userControl来学习如何使用属性。我希望此属性隐藏网格中的第二行。

查看:

    <UserControl x:Class="Test.UserControl1"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300">
    <Grid Margin="0,0,0,0" Name="outergrid" DataContext="{Binding}">
      <Grid.RowDefinitions>
        <RowDefinition Height="3*" />
        <RowDefinition Height="1*" />
    </Grid.RowDefinitions>

    <ContentControl Name="XAMLView" Grid.Row="0"/>
    <GridSplitter ResizeDirection="Rows" 
                Grid.Row="0"
                VerticalAlignment="Bottom" 
                HorizontalAlignment="Stretch" />
    <Border Width="11" Grid.Row="1" Background="Black" />
</Grid>

代码:

public partial class UserControl1 : UserControl
{
    public UserControl1()
    {
        InitializeComponent();
        outergrid.RowDefinitions[1].SetBinding(RowDefinition.HeightProperty, new Binding() { Path = new PropertyPath("ShowCode"), Source = this, Converter = new BoolToHeightConverter(), ConverterParameter = "True" });
    }

    public bool ShowCode
    {
        get { return (bool)GetValue(ShowCodeProperty); }
        set { SetValue(ShowCodeProperty, value); }
    }

    public static readonly DependencyProperty ShowCodeProperty =
        DependencyProperty.Register("ShowCode",
        typeof(bool),
        typeof(UserControl1),
        new PropertyMetadata(true, new PropertyChangedCallback(OnShowCodeChanged)));

    static void OnShowCodeChanged(object sender, DependencyPropertyChangedEventArgs args)
    {
        UserControl1 source = (UserControl1)sender;

        //source.outergrid.RowDefinitions[1].Height = 
    }

    public class BoolToHeightConverter : IValueConverter
    {
        public object Convert(object value, Type targetType,
            object parameter, System.Globalization.CultureInfo culture)
        {
            if ((string)parameter == "False") return "0";
            return "1*";
        }

        public object ConvertBack(object value, Type targetType,
            object parameter, System.Globalization.CultureInfo culture)
        {
            if ((int)parameter == 0) return false;
            return true;
        }
    }
}

问题:当我像这样使用它时:

<xamlviewer:UserControl1 ShowCode="False"/>

转换(...)被调用2次,两次“参数”都是“真”,否则如果ShowCode =“True”,则只调用一次Convert(),“参数”再次为“真”

为什么总是如此?

2 个答案:

答案 0 :(得分:1)

参数始终为true,因为您使其具有该值:

outergrid.RowDefinitions[1].SetBinding(
    RowDefinition.HeightProperty, 
    new Binding() 
    {
        Path = new PropertyPath("ShowCode"), 
        Source = this, 
        Converter = new BoolToHeightConverter(), 
        ConverterParameter = "True" // <---- You are enforcing its value here.
    });

你的转换器无论如何都搞砸了:你必须检查value而不是parameter来正确地来回转换数据:

// NOTE: Your property is BOOL not STRING.
public class BoolToHeightConverter : IValueConverter
{
    public object Convert(object value, Type targetType,
        object parameter, System.Globalization.CultureInfo culture)
    {
        if(value is bool)
            if((bool)value) return new GridLength(1, DataGridLengthUnitType.Star);
            else return new GridLength(0);

        throw new ArgumentException("Not a bool");
    }

    public object ConvertBack(object value, Type targetType,
        object parameter, System.Globalization.CultureInfo culture)
    {
        // You may not need this method at all!
        if(value is GridLength)
            return ((GridLength)value).Value == 0);
        throw new ArgumentException("Not a GridLength");
    }
}

不再需要参数(除非你在其他地方有其他需要)。

答案 1 :(得分:1)

这里至少有两件事是错误的。

  1. 您的转换器返回一个字符串,其中应返回GridLength

  2. 要转换的值将传递到转化器的value参数,而不是parameter,而且是bool

  3. 所以你应该这样写:

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is bool && (bool)value)
        {
            return new GridLength(1, GridUnitType.Star);
        }
    
        return new GridLength(0);
    }
    

    绑定中不需要转换器参数:

    outergrid.RowDefinitions[1].SetBinding(
        RowDefinition.HeightProperty,
        new Binding()
        {
            Path = new PropertyPath("ShowCode"),
            Source = this,
            Converter = new BoolToHeightConverter()
        });