Reputation: 95
I want to change main window color when textbox input changes in WPF application. Currently, when mouse hover or enters the textbox color changes but I will remove this as I do not want this effect. But I want the same effect when mouse cursor enters into textboxes, it should change main back ground colors.
MainWindow background color is:
LightBlue, when mouse cursor enters A inputbox
LightGreen, when mouse cursor enters B inputbox
LightGray,all other cases.
Model.cs
public abstract class ObservableBase : INotifyPropertyChanged
{
public void Set<TValue>(ref TValue field, TValue newValue, [CallerMemberName] string propertyName = "")
{
if (!EqualityComparer<TValue>.Default.Equals(field, default(TValue)) && field.Equals(newValue)) return;
field = newValue;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public abstract class ViewModelBase : ObservableBase
{
public bool IsInDesignMode
=> (bool)DesignerProperties.IsInDesignModeProperty
.GetMetadata(typeof(DependencyObject))
.DefaultValue;
}
MainViewModel.cs
public class MainViewModel : ViewModelBase
{
public MainViewModel()
{
valueAisValid = true;
valueBisValid = true;
if (IsInDesignMode)
{
Calc();
}
}
#region Properties
private string valueA;
public string ValueA
{
get => valueA;
set
{
if (!string.IsNullOrEmpty(value))
{
Set(ref valueA, value);
Set(ref valueAisValid, double.TryParse(ValueA, out double d));
NotifyPropertyChanged(nameof(ValueAIsValid));
Calc();
}
}
}
private bool valueAisValid;
public bool ValueAIsValid => valueAisValid;
private string valueB;
public string ValueB
{
get => valueB;
set
{
if (!string.IsNullOrEmpty(value))
{
Set(ref valueB, value);
Set(ref valueBisValid, double.TryParse(ValueB, out double d));
NotifyPropertyChanged(nameof(ValueBIsValid));
Calc();
}
}
}
private bool valueBisValid;
public bool ValueBIsValid => valueBisValid;
private string valueC;
public string ValueC
{
get => valueC;
set => Set(ref valueC, value);
}
private string valueD;
public string ValueD
{
get => valueD;
set => Set(ref valueD, value);
}
public bool InputsValid => ValueAIsValid && ValueBIsValid;
#endregion
#region Methods
private void Calc()
{
if (InputsValid)
{
double sum = Convert.ToDouble(valueA) + Convert.ToDouble(valueB);
double product = Convert.ToDouble(valueA) * Convert.ToDouble(valueB);
ValueC = sum.ToString(CultureInfo.InvariantCulture);
ValueD = product.ToString(CultureInfo.InvariantCulture);
}
else
{
ValueC = "NAN";
ValueD = "NAN";
}
}
#endregion
}
BoolToBackgroundColorConverter
public class BoolToBackgroundColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null && !(bool)value)
{
return new SolidColorBrush(Colors.Red);
}
else if (value != null && (bool)value && parameter != null)
{
return (SolidColorBrush)parameter;
}
else
{
return new SolidColorBrush(Colors.White);
}
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
Xaml
<Window x:Class="WPFTestApplication.MainWindow"
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:local="clr-namespace:WPFTestApplication.ViewModel"
xmlns:local1="clr-namespace:WPFTestApplication"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Window.Resources>
<local1:BoolToBackgroundColorConverter x:Key="BoolToBackgroundColorConverter"/>
</Window.Resources>
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.Resources>
<SolidColorBrush x:Key="LightGreen" Color="LightGreen" />
<SolidColorBrush x:Key="LightBlue" Color="LightBlue" />
<SolidColorBrush x:Key="white" Color="white" />
<Style TargetType="TextBlock">
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
<Style TargetType="TextBox" x:Key="TextBox">
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Margin" Value="10"/>
<Setter Property="Width" Value="100"/>
<Setter Property="Height" Value="25"/>
<Setter Property="Grid.Column" Value="1"/>
</Style>
<Style TargetType="TextBox" x:Key="TextBoxA" BasedOn="{StaticResource TextBox}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{Binding ValueAIsValid, Converter={StaticResource BoolToBackgroundColorConverter}, ConverterParameter={StaticResource LightBlue}}" />
</Trigger>
</Style.Triggers>
<Setter Property="Background" Value="{Binding ValueAIsValid, Converter={StaticResource BoolToBackgroundColorConverter}, ConverterParameter={StaticResource white}}" />
</Style>
<Style TargetType="TextBox" x:Key="TextBoxB" BasedOn="{StaticResource TextBox}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{Binding ValueBIsValid, Converter={StaticResource BoolToBackgroundColorConverter}, ConverterParameter={StaticResource LightGreen}}" />
</Trigger>
</Style.Triggers>
<Setter Property="Background" Value="{Binding ValueBIsValid, Converter={StaticResource BoolToBackgroundColorConverter}, ConverterParameter={StaticResource white}}" />
</Style>
<Style TargetType="TextBox" BasedOn="{StaticResource TextBox}"/>
</Grid.Resources>
<TextBlock Text="Value A"/>
<TextBox Text="{Binding ValueA, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource TextBoxA}"/>
<TextBlock Text="Value B" Grid.Row="1"/>
<TextBox Text="{Binding ValueB, UpdateSourceTrigger=PropertyChanged}"
Style="{StaticResource TextBoxB}"
Grid.Row="1"/>
<TextBlock Text="Value C" Grid.Row="2"/>
<TextBox Text="{Binding ValueC}"
IsReadOnly="True"
Grid.Row="2"/>
<TextBlock Text="Value D" Grid.Row="3"/>
<TextBox Text="{Binding ValueD}"
IsReadOnly="True"
Grid.Row="3"/>
</Grid>
</Window>
Upvotes: 0
Views: 799
Reputation: 130
I have modified your source code:
<Window x:Class="WpfApplication1.MainWindow"
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:local="clr-namespace:WpfApplication1"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Window.Resources>
<local:BoolToBackgroundColorConverter x:Key="BoolToBackgroundColorConverter"/>
</Window.Resources>
<Grid Background="{Binding BackgroundColor}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Grid HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.Resources>
<SolidColorBrush x:Key="LightGreen" Color="LightGreen" />
<SolidColorBrush x:Key="LightBlue" Color="LightBlue" />
<SolidColorBrush x:Key="LightGray" Color="LightGray" />
<SolidColorBrush x:Key="White" Color="White" />
<Style TargetType="TextBlock">
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
<Style TargetType="TextBox">
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Margin" Value="10"/>
<Setter Property="Width" Value="100"/>
<Setter Property="Height" Value="25"/>
<Setter Property="Grid.Column" Value="1"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
</Trigger>
</Style.Triggers>
<!--<Setter Property="Background" Value="{StaticResource White}" />-->
</Style>
</Grid.Resources>
<TextBlock Text="Value A"/>
<TextBox Text="{Binding ValueA, UpdateSourceTrigger=PropertyChanged}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter" >
<i:InvokeCommandAction Command="{Binding MouseEnterCommand}" CommandParameter="{StaticResource LightBlue}" />
</i:EventTrigger>
<i:EventTrigger EventName="MouseLeave" >
<i:InvokeCommandAction Command="{Binding MouseLeaveCommand}" CommandParameter="{StaticResource White}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
<TextBlock Text="Value B" Grid.Row="1"/>
<TextBox Text="{Binding ValueB, UpdateSourceTrigger=PropertyChanged}" Grid.Row="1">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter" >
<i:InvokeCommandAction Command="{Binding MouseEnterCommand}" CommandParameter="{StaticResource LightGreen}" />
</i:EventTrigger>
<i:EventTrigger EventName="MouseLeave" >
<i:InvokeCommandAction Command="{Binding MouseLeaveCommand}" CommandParameter="{StaticResource White}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
<TextBlock Text="Value C" Grid.Row="2"/>
<TextBox Text="{Binding ValueC}" Grid.Row="2">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter" >
<i:InvokeCommandAction Command="{Binding MouseEnterCommand}" CommandParameter="{StaticResource LightGray}" />
</i:EventTrigger>
<i:EventTrigger EventName="MouseLeave" >
<i:InvokeCommandAction Command="{Binding MouseLeaveCommand}" CommandParameter="{StaticResource White}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
<TextBlock Text="Value D" Grid.Row="3"/>
<TextBox Text="{Binding ValueD}" Grid.Row="3">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter" >
<i:InvokeCommandAction Command="{Binding MouseEnterCommand}" CommandParameter="{StaticResource LightGray}" />
</i:EventTrigger>
<i:EventTrigger EventName="MouseLeave" >
<i:InvokeCommandAction Command="{Binding MouseLeaveCommand}" CommandParameter="{StaticResource White}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
</Grid>
</Grid>
public class MainViewModel : ViewModelBase
{
public ICommand MouseEnterCommand { get; set; }
public ICommand MouseLeaveCommand { get; set; }
public MainViewModel()
{
valueAisValid = true;
valueBisValid = true;
MouseEnterCommand = new RelayCommand<object>(MouseEnterCommandHandler);
MouseLeaveCommand =new RelayCommand<object>(MouseLeaveCommandHandler);
if (IsInDesignMode)
{
Calc();
}
}
#region Properties
private string _backgroundColor;
public string BackgroundColor
{
get { return _backgroundColor; }
set { _backgroundColor = value; NotifyPropertyChanged(nameof(BackgroundColor)); }
}
private string valueA;
public string ValueA
{
get { return valueA; }
set
{
if (!string.IsNullOrEmpty(value))
{
double d;
Set(ref valueA, value);
Set(ref valueAisValid, double.TryParse(ValueA, out d));
NotifyPropertyChanged(nameof(ValueAIsValid));
Calc();
}
}
}
private bool valueAisValid;
public bool ValueAIsValid => valueAisValid;
private string valueB;
public string ValueB
{
get { return valueB; }
set
{
if (!string.IsNullOrEmpty(value))
{
double d;
Set(ref valueB, value);
Set(ref valueBisValid, double.TryParse(ValueB, out d));
NotifyPropertyChanged(nameof(ValueBIsValid));
Calc();
}
}
}
private bool valueBisValid;
public bool ValueBIsValid => valueBisValid;
private string valueC;
public string ValueC
{
get { return valueC; }
set { Set(ref valueC, value); }
}
private string valueD;
public string ValueD
{
get { return valueD; }
set { Set(ref valueD, value); }
}
public bool InputsValid => ValueAIsValid && ValueBIsValid;
#endregion
#region Methods
private void Calc()
{
if (InputsValid)
{
double sum = Convert.ToDouble(valueA) + Convert.ToDouble(valueB);
double product = Convert.ToDouble(valueA) * Convert.ToDouble(valueB);
ValueC = sum.ToString(CultureInfo.InvariantCulture);
ValueD = product.ToString(CultureInfo.InvariantCulture);
}
else
{
ValueC = "NAN";
ValueD = "NAN";
}
}
private void MouseEnterCommandHandler(object parameter)
{
if (parameter != null)
{
BackgroundColor = parameter.ToString();
}
}
private void MouseLeaveCommandHandler(object parameter)
{
if (parameter !=null)
{
BackgroundColor = parameter.ToString();
}
}
#endregion
}
Please add System.Windows.Interactivity dll to the project and Create a RelayCommand class inheriting ICommand interface.
Upvotes: 3
Reputation: 959
Here's the MainWindow.xaml.cs
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
namespace WpfApp1
{
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
AttachCustomBehaviors();
}
// There's a better way of doing this, read attached behavior in wpf
private void AttachCustomBehaviors()
{
TextBoxA.GotFocus += (s, args) => ChangeMainWindowBackground(this, Brushes.LightBlue);
TextBoxB.GotFocus += (s, args) => ChangeMainWindowBackground(this, Brushes.LightGreen);
TextBoxA.LostFocus += (s, args) => ChangeMainWindowBackground(this, Brushes.Gray);
TextBoxB.LostFocus += (s, args) => ChangeMainWindowBackground(this, Brushes.Gray);
}
private void InputFieldsHovered(object sender, MouseEventArgs e)
{
if (!TextBoxA.IsFocused && !TextBoxB.IsFocused)
{
ChangeMainWindowBackground(this, Brushes.Gray);
}
else if(TextBoxA.IsFocused)
{
ChangeMainWindowBackground(this, Brushes.LightBlue);
}
else if (TextBoxB.IsFocused)
{
ChangeMainWindowBackground(this, Brushes.LightGreen);
}
}
private static void ChangeMainWindowBackground(Window window, SolidColorBrush color)
{
window.Background = color;
}
}
}
Here's the updated xaml:
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800"
Background="Gray">
<Window.DataContext>
<local:MainViewModel/>
</Window.DataContext>
<Window.Resources>
<local:BoolToBackgroundColorConverter x:Key="BoolToBackgroundColorConverter"/>
</Window.Resources>
<Grid x:Name="MainGrid" HorizontalAlignment="Center" VerticalAlignment="Center">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.Resources>
<SolidColorBrush x:Key="White" Color="White" />
<Style TargetType="TextBlock">
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
<Style TargetType="TextBox" x:Key="TextBox">
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="Margin" Value="10"/>
<Setter Property="Width" Value="100"/>
<Setter Property="Height" Value="25"/>
<Setter Property="Grid.Column" Value="1"/>
</Style>
<Style TargetType="TextBox" x:Key="TextBoxA" BasedOn="{StaticResource TextBox}">
<Setter Property="Background" Value="{Binding ValueAIsValid, Converter={StaticResource BoolToBackgroundColorConverter}, ConverterParameter={StaticResource White}}" />
</Style>
<Style TargetType="TextBox" x:Key="TextBoxB" BasedOn="{StaticResource TextBox}">
<Setter Property="Background" Value="{Binding ValueBIsValid, Converter={StaticResource BoolToBackgroundColorConverter}, ConverterParameter={StaticResource White}}" />
</Style>
<Style TargetType="TextBox" BasedOn="{StaticResource TextBox}"/>
</Grid.Resources>
<TextBlock Text="Value A"/>
<TextBox x:Name="TextBoxA" Text="{Binding ValueA, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource TextBoxA}" MouseEnter="InputFieldsHovered"/>
<TextBlock Text="Value B" Grid.Row="1"/>
<TextBox x:Name="TextBoxB" Text="{Binding ValueB, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource TextBoxB}" Grid.Row="1" MouseEnter="InputFieldsHovered"/>
<TextBlock Text="Value C" Grid.Row="2"/>
<TextBox x:Name="TextBoxC" Text="{Binding ValueC}" IsReadOnly="True" Background="Gray" Grid.Row="2" MouseEnter="InputFieldsHovered"/>
<TextBlock Text="Value D" Grid.Row="3"/>
<TextBox x:Name="TextBoxD" Text="{Binding ValueD}" Background="Gray" IsReadOnly="True" Grid.Row="3" MouseEnter="InputFieldsHovered"/>
</Grid>
</Window>
Your ViewModel.cs
using System;
using System.Globalization;
namespace WpfApp1
{
public class MainViewModel : ViewModelBase
{
public MainViewModel()
{
valueAisValid = true;
valueBisValid = true;
}
#region Properties
private string valueA;
public string ValueA
{
get => valueA;
set
{
Set(ref valueA, value);
Set(ref valueAisValid, double.TryParse(ValueA, out double d));
NotifyPropertyChanged(nameof(ValueAIsValid));
Calc();
}
}
private bool valueAisValid;
public bool ValueAIsValid => valueAisValid;
private string valueB;
public string ValueB
{
get => valueB;
set
{
Set(ref valueB, value);
Set(ref valueBisValid, double.TryParse(ValueB, out double d));
NotifyPropertyChanged(nameof(ValueBIsValid));
Calc();
}
}
private bool valueBisValid;
public bool ValueBIsValid => valueBisValid;
private string valueC;
public string ValueC
{
get => valueC;
set => Set(ref valueC, value);
}
private string valueD;
public string ValueD
{
get => valueD;
set => Set(ref valueD, value);
}
public bool InputsValid => ValueAIsValid && ValueBIsValid;
#endregion
#region Methods
private void Calc()
{
if (InputsValid)
{
double sum = Convert.ToDouble(valueA) + Convert.ToDouble(valueB);
double product = Convert.ToDouble(valueA) * Convert.ToDouble(valueB);
ValueC = sum.ToString(CultureInfo.InvariantCulture);
ValueD = product.ToString(CultureInfo.InvariantCulture);
}
else
{
ValueC = "NAN";
ValueD = "NAN";
}
}
#endregion
}
}
Upvotes: 1