Question

I would like to change the foreground color of a textbox based on an incoming event (the incoming number differs from the one in the textbox) but then change it back to black if any text is changed through the UI. I have this working in a circuitous way, but I'm not sure of the correct way to do it.

The XAML:

<TextBox Style="{StaticResource recParm}" Foreground="{Binding Path=AcquisitionTimeChangedByInstrument, Converter={StaticResource BooleanToBrush}}"  Name="acquisitionTxtBox" TextChanged="onAcquisitionTimeChanged" >
    <TextBox.Text>
        <Binding Path="AcquisitionTime" Mode="TwoWay" StringFormat="{}{0:F6}" UpdateSourceTrigger="PropertyChanged" >
            <Binding.ValidationRules>
                <vm:AcquisitionTimeRule Min="200e-6" Max="40" />
            </Binding.ValidationRules>
        </Binding>
    </TextBox.Text>
</TextBox>

The code behind:

private void onAcquisitionTimeChanged(object sender, TextChangedEventArgs e)
{
    //acquisitionTxtBox.Foreground = Brushes.Black;
    ((ViewModel)Application.Current.Resources["vm"]).AcquisitionTimeChangedByInstrument = false;
}

AcquisitionTimeChangedByInstrument is a property that raises PropertyChanged on ViewModel. The converter will change the color to black for false and blue for true.

  1. In the form above, it seems to work as described, but it seems an odd way to go about it. If I use the commented line to change the color directly, the binding seems to break. That is, the view stops checking for changes to AcquisitionTimeChangedByInstrument. Why?
  2. What is the correct way to do this?

Please keep in mind I have only been using WPF for a few days; I don't understand advanced features yet.

EDIT (by request)

Eventually I will check to see if the value in the textbox has changed in AcquisitionTime. For now, I am simply setting AcquisitionTimeChangedByInstrument=true when a button is clicked. This will send the PropertyChanged event, but the get will only be called if I haven't previously change acquisitionTxtBox.Foreground in the callback.

[ValueConversion(typeof(bool), typeof(SolidColorBrush))]
public class BooleanToBrushConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (null == value)
        {
            return null;
        }
        if (value is bool)
        {
            if ((bool)value)
            {
                return (SolidColorBrush)Brushes.DeepSkyBlue;
            }
            return (SolidColorBrush)Brushes.Black;
        }

        Type type = value.GetType();
        throw new InvalidOperationException("No type " + type.Name);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
Was it helpful?

Solution

Setting a dependencyproperty locally can take precedence over other settings. Effectively, you end up overwriting the binding. Use

acquisitionTxtBox.SetCurrentValue(ForegroundProperty, Brushes.Black);

Blog entry explaining setcurrentvalue

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top