The attached property is not send to the style
I wanted to create a cell style to show errors and a text with the tooltip.
My style in the xaml dictionary file is this:
<Style TargetType="{x:Type DataGridCell}" x:Key="DataGridCellConErrores">
<Setter Property="ToolTipService.ShowOnDisabled" Value="True"/>
<Setter Property="ToolTipService.InitialShowDelay" Value="5000"/>
<Setter Property="ToolTipService.ShowDuration" Value="60000"/>
<Setter Property="ToolTip">
<Setter.Value>
<MultiBinding Converter="{StaticResource ResourceKey=dlgEnviarAlbaranCantidadParaDescontarTooltipMultivalueConverter}">
<MultiBinding.Bindings>
<Binding Path="(ap:CeldasDatagridConErroresAttachedProperty.TextoTooltip01)"/>
<Binding Path="(ap:CeldasDatagridConErroresAttachedProperty.TextoTooltip02)"/>
</MultiBinding.Bindings>
</MultiBinding>
</Setter.Value>
</Setter>
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=(ap:CeldasDatagridConErroresAttachedProperty.EsDatoCorrecto)}" Value="false"/>
</MultiDataTrigger.Conditions>
<Setter Property="Background" Value="Orange"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
This is how I am trying to use in my column of the datagrid:
<DataGridTextColumn Header="Cantidad Para Descontar" Binding="{Binding CantidadParaDescontar, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, ValidatesOnDataErrors=True}" Width="AUTO" IsReadOnly="false"
ap:CeldasDatagridConErroresAttachedProperty.TextoTooltip01="{Binding Path=DescripcionCantidadParaDescontar}"
ap:CeldasDatagridConErroresAttachedProperty.TextoTooltip02="{Binding Path=MotivoCantidadParaDescontarIncorrecta}"
ap:CeldasDatagridConErroresAttachedProperty.EsDatoCorrecto="{Binding Path=EsCantidadParaDescontarCorrecta}"
CellStyle="{StaticResource DataGridCellConErrores}"/>
I can compile and run, but the text of tooltip is always empty and also it doesn't change the color of the background if the data is not correct.
How should I bind the attached properties?
Thanks.
EDIT 1: I will add a new simplified example that reproduce the same problem. This is the whole code:
The view:
<Window x:Class="TestStyleWithAttachedProperties.MainWindowView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:conv="clr-namespace:TestStyleWithAttachedProperties.Converters"
xmlns:vm="clr-namespace:TestStyleWithAttachedProperties.ViewModels"
xmlns:ap="clr-namespace:TestStyleWithAttachedProperties.AttachedProperties"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<vm:MainWindowViewModel/>
</Window.DataContext>
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="GUIResources.xaml" />
</ResourceDictionary.MergedDictionaries>
<!--<conv:CellTooltipMultiValueConverter x:Key="CellTooltipMultiValueConverter"/>-->
</ResourceDictionary>
</Window.Resources>
<Grid>
<DataGrid Name="dgdTest" Grid.Column="0" Margin="5,5,5,5"
ItemsSource="{Binding Items}"
AutoGenerateColumns="false">
<DataGrid.Columns>
<DataGridTextColumn Header="Price" Binding="{Binding Price}" Width="150"
ap:CellWithErrorsAttachedProperty.TextoTooltip01="{Binding Path=Tooltip}"
ap:CellWithErrorsAttachedProperty.TextoTooltip02="{Binding Path=ErrorDescription}"
ap:CellWithErrorsAttachedProperty.EsDatoCorrecto="{Binding Path=IsDataCorrect}"
CellStyle="{StaticResource DataGridCellWithErrorsStyle}">
</DataGridTextColumn>
<DataGridTextColumn Header="Discount" Binding="{Binding Discount}" Width="150"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
The view model:
using System.Collections.ObjectModel;
namespace TestStyleWithAttachedProperties.ViewModels
{
public class MainWindowViewModel : BaseViewModel
{
public MainWindowViewModel()
{
Items = new ObservableCollection<Data>();
Data miData01 = new Data()
{
Price = 1m,
Discount = 0m,
Tooltip = "Tooltip Data01",
ErrorDescription = "No errors",
IsDataCorrect = true,
};
Items.Add(miData01);
Data miData02 = new Data()
{
Price = 2m,
Discount = 10m,
Tooltip = "Tooltip Data02",
ErrorDescription = "No errors",
IsDataCorrect = true,
};
Items.Add(miData02);
Data miData03 = new Data()
{
Price = -1m,
Discount = 0m,
Tooltip = "Tooltip Data03",
ErrorDescription = "Price has to be greater than 0.",
IsDataCorrect = false,
};
Items.Add(miData03);
}
private ObservableCollection<Data> _items;
public ObservableCollection<Data> Items
{
get { return _items; }
set
{
_items = value;
base.RaisePropertyChangedEvent(nameof(Items));
}
}
}
}
The Data class:
using TestStyleWithAttachedProperties.ViewModels;
namespace TestStyleWithAttachedProperties
{
public class Data : BaseViewModel
{
private decimal _price;
public decimal Price
{
get { return _price; }
set
{
_price = value;
base.RaisePropertyChangedEvent(nameof(Price));
}
}
private decimal _disocunt;
public decimal Discount
{
get { return _disocunt; }
set
{
_disocunt = value;
base.RaisePropertyChangedEvent(nameof(Discount));
}
}
private string _tooltip;
public string Tooltip
{
get { return _tooltip; }
set
{
_tooltip = value;
base.RaisePropertyChangedEvent(nameof(Tooltip));
}
}
private string _errorDescription;
public string ErrorDescription
{
get { return _errorDescription; }
set
{
_errorDescription = value;
base.RaisePropertyChangedEvent(nameof(ErrorDescription));
}
}
private bool _isDataCorrect;
public bool IsDataCorrect
{
get { return _isDataCorrect; }
set
{
_isDataCorrect = value;
base.RaisePropertyChangedEvent(nameof(IsDataCorrect));
}
}
}
}
The GUI xaml resources:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ap="clr-namespace:TestStyleWithAttachedProperties.AttachedProperties"
xmlns:conv="clr-namespace:TestStyleWithAttachedProperties.Converters"
xmlns:sys="clr-namespace:System;assembly=System.Runtime">
<conv:CellTooltipMultiValueConverter x:Key="CellTooltipMultiValueConverter"/>
<Style TargetType="{x:Type DataGridCell}" x:Key="DataGridCellWithErrorsStyle">
<Setter Property="ToolTip">
<Setter.Value>
<MultiBinding Converter="{StaticResource ResourceKey=CellTooltipMultiValueConverter}">
<MultiBinding.Bindings>
<Binding Path="(ap:CellWithErrorsAttachedProperty.TextoTooltip01)" RelativeSource="{RelativeSource AncestorType=DataGridTextColumn}"/>
<Binding Path="(ap:CellWithErrorsAttachedProperty.TextoTooltip02)" RelativeSource="{RelativeSource AncestorType=DataGridTextColumn}"/>
</MultiBinding.Bindings>
</MultiBinding>
</Setter.Value>
</Setter>
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=(ap:CellWithErrorsAttachedProperty.EsDatoCorrecto), RelativeSource={RelativeSource AncestorType=DataGridTextColumn}}" Value="false"/>
</MultiDataTrigger.Conditions>
<Setter Property="Background" Value="Orange"/>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
The attached properties:
using System.Windows;
namespace TestStyleWithAttachedProperties.AttachedProperties
{
public static class CellWithErrorsAttachedProperty
{
//TextoTooltip01
//Primer texto del tooltip que se mostrará.
public static readonly DependencyProperty TextoTooltip01Property =
DependencyProperty.RegisterAttached(
"TextoTooltip01",
typeof(string),
typeof(CellWithErrorsAttachedProperty));
public static string GetTextoTooltip01(DependencyObject obj)
{
return (string)obj.GetValue(TextoTooltip01Property);
}
public static void SetTextoTooltip01(DependencyObject obj, string value)
{
obj.SetValue(TextoTooltip01Property, value);
}
//TextoTooltip02
//Primer texto del tooltip que se mostrará.
public static readonly DependencyProperty TextoTooltip02Property =
DependencyProperty.RegisterAttached(
"TextoTooltip02",
typeof(string),
typeof(CellWithErrorsAttachedProperty));
public static string GetTextoTooltip02(DependencyObject obj)
{
return (string)obj.GetValue(TextoTooltip01Property);
}
public static void SetTextoTooltip02(DependencyObject obj, string value)
{
obj.SetValue(TextoTooltip01Property, value);
}
//ES DATO CORRECTO
//Indica si el dato de la celda es correcto o no.
public static readonly DependencyProperty EsDatoCorrectoProperty =
DependencyProperty.RegisterAttached(
"EsDatoCorrecto",
typeof(bool),
typeof(CellWithErrorsAttachedProperty));
public static bool GetEsDatoCorrecto(DependencyObject obj)
{
return (bool)obj.GetValue(EsDatoCorrectoProperty);
}
public static void SetEsDatoCorrecto(DependencyObject obj, bool value)
{
obj.SetValue(EsDatoCorrectoProperty, value);
}
}
}
Then multivalue converter:
using System;
using System.Globalization;
using System.Windows.Data;
namespace TestStyleWithAttachedProperties.Converters
{
public class CellTooltipMultiValueConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
//here values are unset values.
//If I return a string, it is shown in the datagrid. But I can't do any logic because the values are null.
return "Hola";
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
The base view model that implements INotifyPropertyChanged:
using System.ComponentModel;
namespace TestStyleWithAttachedProperties.ViewModels
{
public abstract class BaseViewModel : INotifyPropertyChanging, INotifyPropertyChanged
{
#region INotifyPropertyChanging Members
public event PropertyChangingEventHandler PropertyChanging;
#endregion
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
#region Administrative Properties
/// <summary>
/// Whether the view model should ignore property-change events.
/// </summary>
public virtual bool IgnorePropertyChangeEvents { get; set; }
#endregion
#region Public Methods
/// <summary>
/// Raises the PropertyChanged event.
/// </summary>
/// <param name="propertyName">The name of the changed property.</param>
public virtual void RaisePropertyChangedEvent(string propertyName)
{
// Exit if changes ignored
if (IgnorePropertyChangeEvents) return;
// Exit if no subscribers
if (PropertyChanged == null) return;
// Raise event
var e = new PropertyChangedEventArgs(propertyName);
PropertyChanged(this, e);
}
/// <summary>
/// Raises the PropertyChanging event.
/// </summary>
/// <param name="propertyName">The name of the changing property.</param>
public virtual void RaisePropertyChangingEvent(string propertyName)
{
// Exit if changes ignored
if (IgnorePropertyChangeEvents) return;
// Exit if no subscribers
if (PropertyChanging == null) return;
// Raise event
var e = new PropertyChangingEventArgs(propertyName);
PropertyChanging(this, e);
}
#endregion
}
}
This is the full code, I don't know if it is allowed to us a link to onedrive to can download the project, if it is possible, I could do it.
Thanks.