Toggle Button Color Bound Property Not Concistant

Marc Jeeves 386 Reputation points
2020-04-09T19:37:23.907+00:00

Can't get my color property's bind logic right. I get odd color behavior and occasionally the toggle switch switches back on its own.

Can anybody help

Thanks

Madaxe

<UserControl x:Class="WpfApp5.ToggleButtonUserControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WpfApp5"
             mc:Ignorable="d" 
             d:DesignHeight="120" d:DesignWidth="240">

    <Grid>
        <Viewbox>
            <Grid Height="120" Width="240" Margin="0,0,0,0" HorizontalAlignment="Left" VerticalAlignment="Top">
                <Rectangle Name="Rec_Back" 
                           MouseLeftButtonDown="Rec_Back_MouseLeftButtonDown" 
                           Fill="{Binding _CurrentColor,FallbackValue=OrangeRed}"
                           Height="115" Width="235" 
                           RadiusY="60" RadiusX="60" 
                           Margin="2.5,2.5,2.5,2.5" 
                           HorizontalAlignment="Left" VerticalAlignment="Top"/>
                <Ellipse Name="Eli_Slider" 
                         MouseLeftButtonDown="Eli_Slider_MouseLeftButtonDown"
                         Fill="{Binding ButtonColor,FallbackValue=White}"
                         Margin="5, 5, 5, 5"
                         Height="110" Width="110" 
                         HorizontalAlignment="Left" VerticalAlignment="Top" />
            </Grid>
        </Viewbox>
    </Grid>
</UserControl>


using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;

namespace WpfApp5
{
    public partial class ToggleButtonUserControl : UserControl
    {
        public bool IsToggled
        {
            get { return (bool)GetValue(IsToggledProperty);}
            set { SetValue(IsToggledProperty, value);}
        }

        public static readonly DependencyProperty IsToggledProperty =
            DependencyProperty.Register("IsToggled", typeof(bool), typeof(ToggleButtonUserControl), 
                new PropertyMetadata(false, new PropertyChangedCallback(ChangeIsToggled)));

        private static void ChangeIsToggled(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if ((bool)e.NewValue == false)
            {
                (d as ToggleButtonUserControl).Eli_Slider.Margin = (d as ToggleButtonUserControl)._LeftThickness;
                (d as ToggleButtonUserControl).Rec_Back.Fill  = (d as ToggleButtonUserControl).SlideColorOff;
                (d as ToggleButtonUserControl)._CurrentColor = (d as ToggleButtonUserControl).SlideColorOff;
            }
            else
            {
                (d as ToggleButtonUserControl).Eli_Slider.Margin = (d as ToggleButtonUserControl)._RightThickness;
                (d as ToggleButtonUserControl).Rec_Back.Fill = (d as ToggleButtonUserControl).SlideColorOn;
                (d as ToggleButtonUserControl)._CurrentColor = (d as ToggleButtonUserControl).SlideColorOn;
            }
        }


        public SolidColorBrush ButtonColor
        {
            get { return (SolidColorBrush)GetValue(ButtonColorProperty); }
            set { SetValue(ButtonColorProperty, value); }
        }
        public static readonly DependencyProperty ButtonColorProperty =
            DependencyProperty.Register("ButtonColor", typeof(SolidColorBrush), typeof(ToggleButtonUserControl), 
                new PropertyMetadata(Brushes.White, new PropertyChangedCallback(ChangeButtonColor)));
        private static void ChangeButtonColor(DependencyObject d, DependencyPropertyChangedEventArgs e) { }

        public SolidColorBrush SlideColorOn
        {
            get { return (SolidColorBrush)GetValue(SlideColorOnProperty); }
            set { SetValue(SlideColorOnProperty, value); }
        }
        public static readonly DependencyProperty SlideColorOnProperty =
            DependencyProperty.Register("SlideColorOn", typeof(SolidColorBrush), typeof(ToggleButtonUserControl), 
                new PropertyMetadata(Brushes.Green, new PropertyChangedCallback(ChangeSlideColorOn)));
        private static void ChangeSlideColorOn(DependencyObject d, DependencyPropertyChangedEventArgs e) { }

        public SolidColorBrush SlideColorOff
        {
            get { return (SolidColorBrush)GetValue(SlideColorOffProperty); }
            set { SetValue(SlideColorOffProperty, value); }
        }
        public static readonly DependencyProperty SlideColorOffProperty =
            DependencyProperty.Register("SlideColorOff", typeof(SolidColorBrush), typeof(ToggleButtonUserControl), 
                new PropertyMetadata(Brushes.OrangeRed, new PropertyChangedCallback(ChangeSlideColorOff)));
        private static void ChangeSlideColorOff(DependencyObject d, DependencyPropertyChangedEventArgs e) { }



        private Thickness _LeftThickness = new Thickness(5, 5, 5, 5);
        private Thickness _RightThickness = new Thickness(125, 5, 5, 5);
        private SolidColorBrush _CurrentColor = null;



        public ToggleButtonUserControl()
        {
            InitializeComponent();
            Eli_Slider.DataContext = this;
            Rec_Back.DataContext = this;
            this._CurrentColor = this.SlideColorOff;
        }

        private void Eli_Slider_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            this.IsToggled = (this.IsToggled) ? false : true;
        }

        private void Rec_Back_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            this.IsToggled = (this.IsToggled) ? false : true;
        }
    }
}
Windows Presentation Foundation
Windows Presentation Foundation
A part of the .NET Framework that provides a unified programming model for building line-of-business desktop applications on Windows.
2,676 questions
0 comments No comments
{count} votes

Accepted answer
  1. Peter Fleischer (former MVP) 19,231 Reputation points
    2020-04-10T07:29:55.44+00:00

    Hi, you can simplify the code like this:

    XAML:

    <UserControl x:Class="WpfControlLibrary1.Window25UC3"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:local="clr-namespace:WpfControlLibrary1"
                 mc:Ignorable="d" 
                 d:DesignHeight="120" d:DesignWidth="240" 
                 PreviewMouseLeftButtonDown="UserControl_PreviewMouseLeftButtonDown">
      <Grid>
        <Viewbox>
          <Grid x:Name="grd">
            <Rectangle Fill="{Binding CurrentColor, FallbackValue=OrangeRed}"
                   Height="115"
                   Width="235"
                   RadiusY="60"
                   RadiusX="60"       
                   Margin="2.5 2.5 2.5 2.5"/>
            <Ellipse Fill="{Binding ButtonColor, FallbackValue=White}"     
                 Margin="5 5 5 5"        
                 Height="110" 
                 Width="110"  
                 HorizontalAlignment="{Binding CurrentPosition, FallbackValue=Left}"/>
          </Grid>
        </Viewbox>
      </Grid>
    </UserControl>
    

    Code:

    using System.ComponentModel;
    using System.Runtime.CompilerServices;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Input;
    using System.Windows.Media;
    
    namespace WpfControlLibrary1
    {
      /// <summary>
      /// Interaction logic for Window25UC3.xaml
      /// </summary>
      public partial class Window25UC3 : UserControl,  INotifyPropertyChanged
      {
        public Window25UC3()
        {
          InitializeComponent();
          this.grd.DataContext = this;
        }
        private void UserControl_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) => IsToggled = !IsToggled;
    
        public bool IsToggled
        {
          get { return (bool)GetValue(IsToggledProperty); }
          set { SetValue(IsToggledProperty, value); }
        }
    
        public static readonly DependencyProperty IsToggledProperty =
            DependencyProperty.Register("IsToggled", typeof(bool), typeof(Window25UC3),
                new PropertyMetadata(false, new PropertyChangedCallback(ChangeIsToggled)));
    
        private static void ChangeIsToggled(DependencyObject d, DependencyPropertyChangedEventArgs e) => 
          (d as Window25UC3).SetDesign((bool)e.NewValue);
    
        public SolidColorBrush ButtonColor
        {
          get { return (SolidColorBrush)GetValue(ButtonColorProperty); }
          set { SetValue(ButtonColorProperty, value); }
        }
        public static readonly DependencyProperty ButtonColorProperty =
            DependencyProperty.Register("ButtonColor", typeof(SolidColorBrush), typeof(Window25UC2),
                new PropertyMetadata(Brushes.White));
    
        public SolidColorBrush SlideColorOn
        {
          get { return (SolidColorBrush)GetValue(SlideColorOnProperty); }
          set { SetValue(SlideColorOnProperty, value); }
        }
        public static readonly DependencyProperty SlideColorOnProperty =
            DependencyProperty.Register("SlideColorOn", typeof(SolidColorBrush), typeof(Window25UC2),
                new PropertyMetadata(Brushes.Green));
    
        public SolidColorBrush SlideColorOff
        {
          get { return (SolidColorBrush)GetValue(SlideColorOffProperty); }
          set { SetValue(SlideColorOffProperty, value); }
        }
        public static readonly DependencyProperty SlideColorOffProperty =
            DependencyProperty.Register("SlideColorOff", typeof(SolidColorBrush), typeof(Window25UC2),
                new PropertyMetadata(Brushes.OrangeRed));
    
        private void ToggleAction()
        {
          IsToggled = !IsToggled;
          SetDesign(IsToggled);
        }
    
        public Brush CurrentColor { get; set; } = Brushes.OrangeRed;
    
        public HorizontalAlignment CurrentPosition { get; set; } = HorizontalAlignment.Left;
    
        private void SetDesign(bool toogleValue)
        {
          CurrentColor = (toogleValue) ? this.SlideColorOn : this.SlideColorOff;
          CurrentPosition = (toogleValue) ? HorizontalAlignment.Right : HorizontalAlignment.Left;
          OnPropChanged(nameof(CurrentColor));
          OnPropChanged(nameof(CurrentPosition));
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropChanged([CallerMemberName] string propertyName = "") =>
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
      }
    }
    
    0 comments No comments

2 additional answers

Sort by: Most helpful
  1. Peter Fleischer (former MVP) 19,231 Reputation points
    2020-04-09T19:49:21.273+00:00

    Hi, you use _CurrentColor for binding. WPF supports only property binding. You must change field _CurrentColor to property.

    private Thickness _LeftThickness = new Thickness(5, 5, 5, 5);
    private Thickness _RightThickness = new Thickness(125, 5, 5, 5);
    **public SolidColorBrush _CurrentColor { get; set; } = null;**
    
    0 comments No comments

  2. Marc Jeeves 386 Reputation points
    2020-04-10T16:44:44.11+00:00

    Thank you so much lots to learn.

    0 comments No comments