1

In the code below, when an invalid value (e.g. "a") is entered in the combobox, an exception is thrown and WPF sets Validation.HasError to true. The combobox trigger dutifully sets the background to blue. However, I would expect the Tag property to be also set to 'true' and as it is databound to B in the underlying datacontext, you may expect B to be updated to 'true' too. However, I understand that, as validation fails, the binding engine stops and does not run any converters - the ConvertBack method below is not called at all .

However, the snoop utility shows Tag as remaining at its "default" value (given by property B in datacontext).

Any insight into why would be greatly appreciated.

<Window
x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Window.Resources>
    <Style TargetType="ComboBox">
        <Style.Triggers>
            <Trigger Property = "Validation.HasError" Value = "true">
                <Setter Property="Tag" Value="true"/>
                <Setter Property="Background" Value="Blue"/>
            </Trigger>
        </Style.Triggers>
    </Style>
</Window.Resources>
<StackPanel>
    <ComboBox Height="23" IsEditable="True" Name="comboBox1" Width="120"   
              Tag="{Binding Path=B, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource MyConverter}}"
            Text="{Binding Path=A, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=True}"/>
</StackPanel>

public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContextClass dataContext = new DataContextClass ();
            this.DataContext = dataContext ;

        }

    }

    public class DataContextClass : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged = delegate { };
            private string b = "default";
            public string B
            {
                get { return b; }
                set
                {
                    b = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("B"));
                }
            }

            private int a;
            public int A
            {
                get { return a; }
                set
                {
                    a = value;
                    PropertyChanged(this, new PropertyChangedEventArgs("A"));
                }
            }
        }


 public class MyConverter : IValueConverter
    {
        #region Public Methods

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value;
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return value as string;
        }

        #endregion
    }
sturdytree
  • 849
  • 3
  • 12
  • 26

1 Answers1

2

This is simply due to dependency property precedence. You've set a local value for the Tag property, which takes precedence over your style trigger. Background, on the other hand, has no local value specified so value set by the style trigger becomes the effective value.

See Dependency Property Value Precedence on MSDN.

Kent Boogaart
  • 175,602
  • 35
  • 392
  • 393
  • Thanks Kent, very good. Is there some way to access the HasError value in the DataContext(ViewModel)? that is what I am trying to achieve. – sturdytree Mar 03 '12 at 11:04
  • @sturdytree: you could bind `Validation.HasError` to a property on your VM using `Mode=OneWayToSource`. – Kent Boogaart Mar 03 '12 at 12:46
  • Kent, thanks, but Validation.HasError="{Binding Path=B, Mode=OneWayToSource}" results in compile error "Validation.HasError is read only and cannot be set from mark up" – sturdytree Mar 03 '12 at 13:40
  • A limitation of WPF I always forget because it's so unintuitive. You cannot bind a read-only property, not even `OneWayToSource`. You can work around it with an attached behavior discussed elsewhere, including here: http://stackoverflow.com/questions/1083224/pushing-read-only-gui-properties-back-into-viewmodel – Kent Boogaart Mar 03 '12 at 14:43