Edit: I created a sample project displaying what I have done and what doesn't work. https://github.com/jmooney5115/clear-multibinding
I have a WPF application with controls (textbox, datagrid, etc). When a value changes on the control I need to indicate it by changing the background color. After saving changes the background color needs to go back to the unchanged state without reloading the control. This application is not MVVM, don't judge I inherited it.
I have the code working perfectly for changing the color using MultiBinding and a value converter. The problem is I cannot figure out how to reset the background after calling Save() in my code. I have tried doing DataContext = null and then DataContext = this but the control flickers. There has to be a better way.
Q: how can I reset the background to the unchanged state without reloading the control?
MultiBinding XAML - this works by passing a string[] to BackgroundColorConverter. string[0] is the OneTime binding. string1 is the other binding.
<TextBox.Background>
<MultiBinding Converter="{StaticResource BackgroundColorConverter}">
<Binding Path="DeviceObj.Name" />
<Binding Path="DeviceObj.Name" Mode="OneTime" />
</MultiBinding>
</TextBox.Background>
BackgroundColorConverter.cs
/// <summary>
/// https://stackoverflow.com/questions/1224144/change-background-color-for-wpf-textbox-in-changed-state
///
/// Property changed
/// </summary>
public class BackgroundColorConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
var colorRed = (System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("#FFB0E0E6");
var colorWhite = (System.Windows.Media.Color)System.Windows.Media.ColorConverter.ConvertFromString("White");
var unchanged = new SolidColorBrush(colorWhite);
var changed = new SolidColorBrush(colorRed);
if (values.Length == 2)
if (values[0].Equals(values[1]))
return unchanged;
else
return changed;
else
return changed;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Updates
Edit: this is the multi binding for a data grid cell. If the multi binding converter returns true, set the background color to LightBlue. If false, the background is the default color.
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Path=Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" >
<!-- https://stackoverflow.com/questions/5902351/issue-while-mixing-multibinding-converter-and-trigger-in-style -->
<DataGridTextColumn.CellStyle>
<Style TargetType="{x:Type DataGridCell}">
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource BackgroundColorConverterBool}">
<Binding Path="Name" />
<Binding Path="Name" Mode="OneTime" />
</MultiBinding>
</DataTrigger.Binding>
</DataTrigger>
<Setter Property="Background" Value="LightBlue"></Setter>
</Style.Triggers>
</Style>
</DataGridTextColumn.CellStyle>
</DataGridTextColumn>
.
.
.
</DataGrid.Columns>
I made this method to reset the binding of objects after saving.
/// <summary>
/// Update the data binding after a save to clear the blue that could be there when
/// a change is detected.
/// </summary>
/// <typeparam name="T">Type to search for</typeparam>
/// <param name="parentDepObj">Parent object we want to reset the binding for their children.</param>
public static void UpdateDataBinding<T>(DependencyObject parentDepObj) where T : DependencyObject
{
if (parentDepObj != null)
{
MultiBindingExpression multiBindingExpression;
foreach (var control in UIHelper.FindVisualChildren<T>(parentDepObj))
{
multiBindingExpression = BindingOperations.GetMultiBindingExpression(control, Control.BackgroundProperty);
if (multiBindingExpression != null)
multiBindingExpression.UpdateTarget();
}
}
}
Final Update
This question answers how to use MultiBinding for my purpose on DataGridCell: Update MultiBinding on DataGridCell