【问题标题】:Binding errors While Binding null values to Width and Height of the wpf control将空值绑定到 wpf 控件的宽度和高度时出现绑定错误
【发布时间】:2012-06-15 07:22:52
【问题描述】:

我们的项目需要我们绑定控件的许多属性,例如HeightWidthMinHeightRowColumnrowspan...等。这样做时我们观察到绑定当这些值是 null 时出现错误,我们将从 DB 中获取。

为了说明,我的 MainWindow.xaml.cs 看起来像这样。

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        //TextWidth  id null
        TextBlockSize1 = new ItemSize() { TextHeight=20 };
        //TextWidth is null
        TextBlockSize2 = new ItemSize() { TextWidth = 40 };
        //TextHeight is null and TextWidth is null
        TextBlockSize3 = new ItemSize() { TextWidth = 40 };
        textblock1.DataContext = TextBlockSize1;
        textblock2.DataContext = TextBlockSize2;
        textblock3.DataContext = TextBlockSize3;
    }
    public ItemSize TextBlockSize1 { get; set; }

    public ItemSize TextBlockSize2 { get; set; }

    public ItemSize TextBlockSize3 { get; set; }
}

public class ItemSize
{
    public double? TextHeight { get; set; }
    public double? TextWidth { get; set; }
}

MainWindow.xaml 看起来像这样。

<Window x:Class="WPfAppln1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:ctrl="clr-namespace:WPfAppln1.Controls"
    Title="MainWindow" Height="350" Width="525">
    <StackPanel >
         <TextBlock Name="textblock1" Text=" TextBlock 1"  Width="{Binding TextWidth}"  Height="{Binding TextHeight}"></TextBlock>
         <TextBlock Name="textblock2" Text=" TextBlock 2"  Width="{Binding TextWidth}"  Height="{Binding TextHeight}"></TextBlock>
         <TextBlock Name="textblock3" Text=" TextBlock 3"  Width="{Binding TextWidth, TargetNullValue=Auto}"  Height="{Binding TextHeight, TargetNullValue=Auto}"></TextBlock>     
   </StackPanel>
</Window>

在输出窗口中显示以下绑定错误:

System.Windows.Data Error: 5 : 'WPfAppln1.vshost.exe' (Managed (v4.0.30319)): Loaded 'C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Numerics\v4.0_4.0.0.0__b77a5c561934e089\System.Numerics.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled.
Value produced by BindingExpression is not valid for target property.; Value='<null>' BindingExpression:Path=TextWidth; DataItem='ItemSize' (HashCode=43929715); target element is 'TextBlock' (Name='textblock1'); target property is 'Width' (type 'Double')
System.Windows.Data Error: 5 : Value produced by BindingExpression is not valid for target property.; Value='<null>' BindingExpression:Path=TextHeight; DataItem='ItemSize' (HashCode=57104612); target element is 'TextBlock' (Name='textblock2'); target property is 'Height' (type 'Double')
System.Windows.Data Error: 5 : Value produced by BindingExpression is not valid for target property.; Value='<null>' BindingExpression:Path=TextHeight; DataItem='ItemSize' (HashCode=59587750); target element is 'TextBlock' (Name='textblock3'); target property is 'Height' (type 'Double')
    The thread '<No Name>' (0x2c60) has exited with code 0 (0x0).

由于这些错误,应用程序需要很长时间才能加载屏幕。

所以问题是如何在绑定到 wpf 控件时容纳可为空的值,以及如何在绑定值为空时为控件的宽度属性提供默认值,例如“自动”。

【问题讨论】:

  • 您确定这些绑定错误会减慢您的应用程序的速度吗?我只是古玩,因为我一直认为输出窗口中的绑定错误不会影响性能....
  • @SvenG :是的,这些绑定错误可能会导致性能问题,我个人在使用 DataGrid 时遇到过这个问题。 Here 是一个 MS 链接,上面写着 -“WPF 尝试了几种不同的方法来解决路径错误,包括搜索附加属性,这非常昂贵”,另请参阅 this
  • 感谢您的洞察,这对我来说非常有用!

标签: c# .net wpf binding double


【解决方案1】:

您可以使用TargetNullValue(如果源为空)或FallbackValue(如果绑定失败,例如DataContextnull

更新:

感谢 Dean 指出这一点,我错误地认为 Auto 会起作用(即TypeConverter 会负责转换)。

但是,您仍然可以使用自动属性并在 XAML 中使用 x:Static Markup Extension 像这样提供 Auto 值 -

<TextBlock Name="textblock1" Text=" TextBlock 1"  
    Height="{Binding TextHeight, TargetNullValue={x:Static System:Double.NaN}, 
               FallbackValue={x:Static System:Double.NaN}}">
</TextBlock> 

Value="{x:Static System:Double.NaN}" 也可以像这样用于DataTrigger 方法 -

<TextBlock.Style>
    <Style>
       <Setter Property="Control.Width" Value="{Binding Path=TextWidth}" />
        <Style.Triggers>
            <DataTrigger
               Binding="{Binding Path=TextWidth}"
               Value="{x:Null}">
               <Setter Property="Control.Width" Value="{x:Static System:Double.NaN}" />
            </DataTrigger>
        </Style.Triggers>
    </Style>
</TextBlock.Style>

注意:将需要这个命名空间 -

xmlns:System="clr-namespace:System;assembly=mscorlib" 

旧代码:

<TextBlock Name="textblock1" Text=" TextBlock 1"  Width="{Binding TextWidth}"  
    Height="{Binding TextHeight, TargetNullValue=Auto, FallbackValue=Auto }">
</TextBlock> 

另一种解决方案是使用这样的触发器 -

<TextBlock.Style>
    <Style>
        <Style.Triggers>
            <DataTrigger
                Binding="{Binding Path=TextWidth}"
                Value="{x:Null}">
                <Setter Property="Control.Width" Value="Auto" />
            </DataTrigger>
            <DataTrigger
                Binding="{Binding Path=TextHeight}"
                Value="{x:Null}">
                <Setter Property="Control.Height" Value="Auto" />
            </DataTrigger>
        </Style.Triggers>
    </Style>
</TextBlock.Style>

【讨论】:

  • -1 :您不能将字符串“Auto”用作 TargetNullValue 或 FallbackValue,因此您的解决方案将不起作用
  • +1 感谢 TargetNullValue。我只是想在 bool 目标中重用一个可为空的 bool,所以这行得通IsEnabled="{Binding Path=ItemEnabled, Converter={StaticResource negate}, TargetNullValue=false}"
  • @reasra 很高兴它有帮助:)
【解决方案2】:

最简单的解决方案(在我看来)是不使用自动属性。

例如

private double textHeight = Double.NaN;
public double TextHeight
{
    get { return textHeight; }
    set { textHeight = value; }
}

private double textWidth = Double.NaN;
public double TextWidth
{
    get { return textWidth; }
    set { textWidth = value; }
}

【讨论】:

  • 我使用依赖属性,但这对我有用。这就是我得到的:公共双重?高度 { get => (double)GetValue(HeightProperty); set { if (value == null) Height = double.NaN;否则设置值(高度属性,值); } }
【解决方案3】:

如果您的两个double? 属性不需要绝对可以为空,您可以将它们设为常规double 属性。这将默认为 0。

如果这是不可能的,或者 0 是不可接受的默认值,我自己会赞成 FallbackValue 解决方案。如果您的默认值必须是“自动”(如上所述),则不能将“自动”设置为FallbackValue

Height和Width的默认值不是0;它是 Double.NaN。 高度和宽度支持成为未设置的“自动”值的能力。 因为 Height 和 Width 是双精度值,所以 Double.NaN 用作 表示此“自动”行为的特殊值。 (来自http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.width(v=VS.95).aspx

如果您不能将Double.NaN 设置为FallbackValue(我没有尝试过),我会自己使用转换器。如果目标值为null,则改为返回Double.NaNhttp://msdn.microsoft.com/en-us/library/system.windows.data.ivalueconverter.aspx 了解有关 IVALueConverter 的更多信息。

【讨论】:

    猜你喜欢
    • 2011-08-17
    • 2012-09-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-18
    • 1970-01-01
    • 2011-06-14
    相关资源
    最近更新 更多