Я пытаюсь установить значение по умолчанию в свой DataGridTextColumn в случае, если свойство привязки дает нулевое значение, например, и если на сервере sql ...
Итак, я исследовал и нашел свойство TargetNullValue, где я могу указать значение по умолчанию, если столбец имеет значение NULL.
Но не работает, как я. Выдает мне следующую ошибку
System.Windows.Markup.XamlParseException: 'Привязка' не может быть установлена для свойства 'TargetNullValue' типа 'Binding'. «Привязка» может быть установлена только для свойства DependencyProperty объекта DependencyObject.
Вот пример моего кода 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 с использованием DataSource ...
Огромное спасибо заранее!
* Обновлен КЛАСС
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);
}
}
** И, наконец, вот результат запроса в режиме отладки ...
Спасибо, Дэйв М! Я понимаю использование мульти-привязок и целей, но пока не знаю, как поместить их в свой DataGrid с помощью CollectionViewSource. Какие-нибудь рекомендации? Заранее спасибо!





Вы не можете привязаться к TargetNullValue. Вы можете указать только жестко запрограммированное значение. Если вы хотите связать, вы можете использовать DataGridTemplateColumn с Textblock и использовать 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, поэтому ... я должен сначала сослаться на него, чтобы предоставить данные ?? ПД: Я очень ценю ваше время !.
@ReyHerrera Я обновил свой ответ, указав, как использовать DataTemplate. Использование CollectionViewSource не имеет значения.
Джеймс, еще раз спасибо! Работает как шарм, но в какой-то момент мне кажется, что это не проверка значения x: Null. Я использовал <Style.Triggers> <DataTrigger Binding = "{Binding Path = Municipio}" Value = "{x: Null}"> <Setter Property = "Text" Value = "{Binding Path = CCodigoPostal.Municipio} "> </Setter> </DataTrigger> </Style.Triggers>
<Style.Triggers> <DataTrigger Binding = "{Binding Path = Municipio}" Value = "{x: Статическая система: DBNull.Value}"> <Setter Property = "Text" Value = "{Binding Path = CCodigoPostal.Municipio} "> </Setter> </DataTrigger> </Style.Triggers>
<Style.Triggers> <DataTrigger Binding = "{Binding Path = Municipio}" Value = "{x: Static system: String.Empty}"> <Setter Property = "Text" Value = "{Binding Path = CCodigoPostal.Municipio} "> </Setter> </DataTrigger> </Style.Triggers>
но не меняет значение в конце, я думаю, что триггер не соответствует нулевому значению, возвращаемому с Sql Server.
@ReyHerrera Какой тип у Municipio, и уверены ли вы, что это значение null? Если это string, вы можете столкнуться с тем, что на самом деле это не null. Вместо этого это будет пустая строка.
Что ж, я почти уверен, что моя таблица sql server возвращает null, но я не знаю, как мой DataGrid принимает значение, поэтому я пробовал эти триггеры ... кстати, Municipio - это varchar на sql server и string в C# (entity framework.
@ReyHerrera Хорошо, я думаю, вместо того, чтобы проверять null, вам нужно проверять пустую строку. Так что замените {x:Null} на пустые кавычки и посмотрите, исправит ли это это.
ну уже пробовал, но все равно не работает ... а почему? мне нужно сделать преобразование?
@ReyHerrera Можете ли вы проверить исходные данные, прежде чем настраивать сетку для проверки фактического значения? Часто, когда вы работаете с strings, они не будут нулевыми. Вместо этого они будут просто пустыми.
Джеймс, еще раз спасибо и извините за беспокойство ... но я отлаживаю его, и он возвращает значение null. Я думаю, проблема в том, что триггер не срабатывает, потому что я выполнил проверку с другим строковым условием и не работает ... но почему?
@ReyHerrera Хорошо. Измените привязку обратно на ту, которую я указал в своем ответе, но добавьте к ней OneWay. Binding = "{Binding Path=Municipio, Mode=OneWay}". Пока вы используете INotifyPropertyChanged в своем классе, он должен работать.
@ReyHerrera Можете ли вы опубликовать класс элементов, к которым вы привязаны?
@ReyHerrera Посмотрите, здесь. Вам необходимо включить INotifyPropertyChanged в свой класс Proveedor, чтобы ваша привязка могла получать обновления. Это единственное, о чем я могу думать.
Это не то, что делает или должен делать TargetNullValue. Что вам нужно, так это MultiBinding с IMultiValueConverter, который возвращает первое ненулевое значение.