如何在WPF XAML的DataGridTextColumn中将绑定值设置为TargetNullValue属性

4
我正在尝试在DataGridTextColumn中设置默认值,以防绑定属性给出Null值,类似于sql server中的if语句...
因此,我进行了研究,并找到了TargetNullValue属性,可以在列为空时放置默认值。
但是它并没有按照我的方式工作。抛出了下一个错误
System.Windows.Markup.XamlParseException:“不能在类型为'Binding'的'TargetNullValue'属性上设置'Binding'。只能在DependencyObject的DependencyProperty上设置'Binding'。”
以下是我的XAML代码示例。
<DataGrid x:Name="proveedorDataGrid" AutoGenerateColumns="False" EnableRowVirtualization="True" ItemsSource="{Binding IsAsync=True}" Margin="15,50,25,70" RowDetailsVisibilityMode="VisibleWhenSelected"
              SelectionMode="Single" IsReadOnly="True" CanUserAddRows="False" CanUserResizeRows="False" CanUserDeleteRows="False" PreviewKeyDown="ProveedorDataGrid_OnPreviewKeyDown">
        <DataGrid.Columns>
            <DataGridTextColumn x:Name="municipioColumn" Binding="{Binding Municipio, TargetNullValue={Binding CCodigoPostal.Municipio}}" Header="Municipio" Width="Auto" />
        </DataGrid.Columns>
    </DataGrid>

当前资源情况下

<Window.Resources>
    <CollectionViewSource x:Key="proveedorViewSource" d:DesignSource="{d:DesignInstance {x:Type Core:Proveedor}, CreateList=True}"/>
</Window.Resources>

实际上,它是使用数据源绑定到EntityFramework...

非常感谢您的帮助!

*更新后的CLASS

public class Proveedor
{
    public Proveedor()
    {
        ValeVehiculoCombustibles = new HashSet<ValeVehiculoCombustible>();
        FacturaProveedors = new HashSet<FacturaProveedor>();
        EntradaBasculas = new HashSet<EntradaBascula>();
    }

    public Guid? Id_Proveedor { get; set; }

    public string Codigo { get; set; }

    public string RazonSocial { get; set; }

    public string Calle { get; set; }

    public string Colonia { get; set; }

    public virtual C_CodigoPostal CCodigoPostal { get; set; }
    public int CCodigoPostalId { get; set; }

    public string Telefonos { get; set; }

    public string RFC { get; set; }

    public virtual CuentaContable CuentaContable { get; set; }
    public Guid? CuentaContableId { get; set; }

    public short DiasCred { get; set; }

    public decimal SaldoMN { get; set; }

    public decimal AnticipoMN { get; set; }

    public decimal SaldoDlls { get; set; }

    public decimal AnticipoDlls { get; set; }

    public string Contacto { get; set; }

    public string Email { get; set; }

    public string Municipio { get; set; }

    public string Estado { get; set; }

    public string Ciudad { get; set; }

    public bool Estatus { get; set; }

    public DateTime Actualizado { get; set; }

    public virtual ICollection<ValeVehiculoCombustible> ValeVehiculoCombustibles { get; set; }
    public virtual ICollection<FacturaProveedor> FacturaProveedors { get; set; }
    public virtual ICollection<EntradaBascula> EntradaBasculas { get; set; }
}

** 和他的配置

public class ProveedorConfiguration : EntityTypeConfiguration<Proveedor>
{
    public ProveedorConfiguration()
    {
        ToTable("Proveedor");

        //PK
        HasKey(p => p.Id_Proveedor);

        Property(p => p.Id_Proveedor)
            .IsRequired()
            .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

        Property(p => p.Codigo)
            .IsRequired()
            .HasColumnType("varchar")
            .HasMaxLength(6);
        HasIndex(p => p.Codigo)
            .IsUnique();

        Property(p => p.RazonSocial)
            .IsRequired()
            .HasColumnType("varchar")
            .HasMaxLength(60);

        Property(p => p.Calle)
            .IsRequired()
            .HasColumnType("varchar")
            .HasMaxLength(40);

        Property(p => p.Colonia)
            .HasColumnType("varchar")
            .HasMaxLength(30);

        Property(p => p.CCodigoPostalId)
            .IsRequired()
            .HasColumnType("int");

        Property(p => p.Telefonos)
            .HasColumnType("varchar")
            .HasMaxLength(30);

        Property(p => p.RFC)
            .HasColumnType("varchar")
            .HasMaxLength(13);
        HasIndex(p => p.RFC)
            .IsUnique();

        Property(p => p.CuentaContableId)
            .IsRequired();

        Property(p => p.DiasCred)
            .IsRequired()
            .HasColumnType("smallint");

        Property(p => p.SaldoMN)
            .IsRequired()
            .HasColumnType("decimal")
            .HasPrecision(10, 2);

        Property(p => p.AnticipoMN)
            .IsRequired()
            .HasColumnType("decimal")
            .HasPrecision(10, 2);

        Property(p => p.SaldoDlls)
            .IsRequired()
            .HasColumnType("decimal")
            .HasPrecision(8, 2);

        Property(p => p.AnticipoDlls)
            .IsRequired()
            .HasColumnType("decimal")
            .HasPrecision(8, 2);

        Property(p => p.Contacto)
            .HasColumnType("varchar")
            .HasMaxLength(60);

        Property(p => p.Email)
            .HasColumnType("varchar")
            .HasMaxLength(90);

        Property(p => p.Municipio)
            .HasColumnType("varchar")
            .HasMaxLength(50);

        Property(p => p.Estado)
            .HasColumnType("varchar")
            .HasMaxLength(31);

        Property(p => p.Ciudad)
            .HasColumnType("varchar")
            .HasMaxLength(45);

        Property(p => p.Estatus)
            .IsRequired();

        //Relationships
        //FK Proveedor -> ValeVehiculoCombustible
        HasMany(p => p.ValeVehiculoCombustibles)
            .WithOptional(v => v.Proveedor)
            .HasForeignKey(v => v.ProveedorId)
            .WillCascadeOnDelete(false);

        //PK Proveedor -> FacturaProveedor
        HasMany(p => p.FacturaProveedors)
            .WithRequired(f => f.Proveedor)
            .HasForeignKey(f => f.ProveedorId)
            .WillCascadeOnDelete(false);

        //FK Proveedor -> EntradaBasucla
        HasMany(p => p.EntradaBasculas)
            .WithRequired(e => e.Proveedor)
            .HasForeignKey(e => e.ProveedorId)
            .WillCascadeOnDelete(false);
    }
}

最后,在调试模式下,这是查询的返回结果...

查看源代码结果


1
这不是TargetNullValue的作用或预期的作用。你需要使用一个IMultiValueConverter的MultiBinding,它返回第一个非空值。 - Dave M
谢谢Dave M!我理解多绑定和用途,但还不知道如何将它们添加到我的DataGrid中使用CollectionViewSource。有什么建议吗?提前致谢! - Rey Herrera
1个回答

3
您无法绑定到 TargetNullValue,只能在其中放入硬编码的值。如果您想进行绑定,可以使用一个具有 TextBlockDataGridTemplateColumn 并在其上使用一个 DataTrigger 来更改该值。
因此,默认情况下,将Textblock绑定到Municipio,然后如果它是{x:Null},则将其绑定到CCodigoPostal.Municipio
<DataGrid.Columns>
    <DataGridTemplateColumn>
        <DataGridTemplateColumn.CellTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding Path=Municipio}">
                     <TextBlock.Style>
                         <Style TargetType="TextBlock">
                             <Setter Property="Text" Value="{Binding Path=Municipio}"></Setter>
                             <Style.Triggers>
                                 <DataTrigger Binding="{Binding Path=Municipio}" Value="{x:Null}">
                                     <Setter Property="Text" Value="{Binding Path=CCodigoPostal.Municipio}"></Setter>
                                  </DataTrigger>
                              </Style.Triggers>
                          </Style>
                      </TextBlock.Style>
                  </TextBlock>
              </DataTemplate>
          </DataGridTemplateColumn.CellTemplate>
      </DataGridTemplateColumn>
  </DataGrid.Columns>

如果你想要更进一步(并且做得对),你应该在资源中创建一个 DataTemplate ,然后只需引用它,而不是将所有的 xaml 直接放在一行中。
如果你想使用资源,你应该将 DataTemplate 放在你的 Windows.Resources 中。
 <Window.Resources>
        <DataTemplate x:Key="template">
            <TextBlock Text="{Binding Path=Municipio}">
                <TextBlock.Style>
                    <Style TargetType="TextBlock">
                        <Setter Property="Text" Value="{Binding Path=Municipio}"></Setter>
                        <Style.Triggers>
                            <DataTrigger Binding="{Binding Path=Municipio}" Value="{x:Null}">
                                <Setter Property="Text" Value="{Binding Path=CCodigoPostal.Municipio}"></Setter>
                            </DataTrigger>
                        </Style.Triggers>
                    </Style>
                </TextBlock.Style>
            </TextBlock>
        </DataTemplate>
    </Window.Resources>

然后,设置 CellTemplate

 <DataGrid x:Name="grid" Grid.Row="3">
            <DataGrid.Columns>
                <DataGridTemplateColumn CellTemplate="{StaticResource template}">
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>

嗨,詹姆斯!非常感谢您的回答,我明白了DataTemplate和触发器的要点...但是我不知道如何将它们作为资源放置...顺便说一下,使用{Binding Path=Municipio}没有给我任何值,请注意我正在使用CollectionViewSource来填充DataGrid,所以...我必须先引用它才能提供数据吗?附言:非常感谢您的时间!。 - Rey Herrera
@ReyHerrera 我已经更新了我的答案,告诉你如何使用DataTemplate。使用CollectionViewSource没有关系。 - Brandon
詹姆斯,再次感谢!它的工作效果很好,但在某些情况下,我认为它没有验证x:Null值。我一直在使用<Style.Triggers> <DataTrigger Binding="{Binding Path=Municipio}" Value="{x:Null}"> <Setter Property="Text" Value="{Binding Path=CCodigoPostal.Municipio}"></Setter> </DataTrigger> </Style.Triggers> - Rey Herrera
但是最终并没有改变该值,我认为触发器无法匹配从SQL Server返回的空值。 - Rey Herrera
@ReyHerrera 好的,我认为你需要检查空字符串而不是null。因此,请将{x: Null}更改为空引号,并查看是否可以解决问题。 - Brandon
显示剩余10条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接