Click here to Skip to main content
15,891,184 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello,

I am new to C#,i have few doubts regarding the MVVM. When to use the IVauleConverter and the binding concept? To understand the concept,I have written a small demo project.
Actually I am trying to implement the small project where i have first name ,last name,full name, timer and ellipse.The timer text box has to display the time when ever the time handler event arises and the color of ellipse has to change. I want to write code for ui separately and logic must be different.In the below code,Its not displaying the time in timer text box.

What I have tried:

C#
private DispatcherTimer atimer;
        public Person personobj { get; set; }

       public MainWindow()
        {
            InitializeComponent();
            personobj = new Person();
            personobj.firstName = "hello";
            personobj.lastName= "";
           
            this.DataContext = personobj;
            // aTimer = new System.Timers.Timer(2000);
            // aTimer.Elapsed += new ElapsedEventHandler(OnTimeEvent);
            // aTimer.Enabled = true;
         //   atimer = new DispatcherTimer();
           // atimer.Interval = TimeSpan.FromMilliseconds(5000);
            //atimer.Tick += new EventHandler(OnTimeEvent);
            //atimer.Start();

        }

        /*private void OnTimeEvent(object sender, EventArgs e)
        {
            //TimerCount.Text = DateTime.Now.ToString("hh:mm:ss");
           // throw new NotImplementedException();
        }*/
    }

    public class Person : INotifyPropertyChanged
    {
        
        /// <summary>
        /// 
        /// 
        public String firstName;
        public String lastName;
        public String fullName="";
        private Boolean colorchange=false;
        private String timeIndicator;
        private DispatcherTimer timeCount;
        public Person()
        {
            timeCount = new DispatcherTimer();
            timeCount.Tick += new EventHandler(Timer_Tick);
            timeCount.Interval = TimeSpan.FromMilliseconds(5000);
            timeCount.Start();

        }
        public String FirstName
        {
            get
            {
                return firstName;
            }

            set
            {
                if (firstName != value)
                {
                    firstName = value;
                    OnPropertyChanged("FirstName");
                    OnPropertyChanged("FullName");
                }
            }
        }

        public String LastName
        {
            get
            {
                return lastName;
            }

            set
            {
                if (lastName != value)
                {
                    lastName = value;
                    OnPropertyChanged("LastName");
                    OnPropertyChanged("FullName");
                }
            }
        }

        public String FullName
        {
            get
            {
                //  Debug.WriteLine(fullName);
                return this.fullName = firstName + " " + lastName;

            }

            set
            {
                this.fullName = value;
                OnPropertyChanged("FullName");
                /*if (fullName != "")
                  {
                      colorchange = false;
                  }
                  else
                  {
                      colorchange = true;
                  }*/



                  }
            }


        public Boolean Colorchange
        {
            get
            {
                return colorchange;
            }

            set
            {
                colorchange = value;
                OnPropertyChanged("Colorchange");
            }
        }

        public string TimeIndicator
        {
            get
            {
                return timeIndicator;
            }

            set
            { 
                timeIndicator = value;
               if (timeIndicator != null)
                  {
                      colorchange = true;
                  }
                  else
                  {
                      colorchange = false;
                  }

                OnPropertyChanged("TimeIndicator");
            }
        }
      

        private void Timer_Tick(object sender, EventArgs e)
        {
            TimeIndicator = DateTime.UtcNow.ToString("hh:mm:ss");
        //    OnPropertyChanged("TimeIndicator");
        }
      //  public delegate PropertyChangedEventHandler(string property);
        public event PropertyChangedEventHandler PropertyChanged;

        private void OnPropertyChanged(string property)
        {
            if (PropertyChanged != null)
            {
                 PropertyChanged(this, new PropertyChangedEventArgs(property));
        //        PropertyChanged(property);
            }
        }


    }
   // [ValueConversion(typeof(Person), typeof(Brush))]
    public class ColorChange : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
         //  Boolean BooleanValue = (Boolean)value;
         
            if (value.ToString()!= null)
            {

                return value.ToString();

            }
            else
            {
                return (object)Brushes.Green;
            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
           if (value is bool)
            {
                if ((bool)value == true)
                    return new SolidColorBrush(Colors.Green);
                else
                    return new SolidColorBrush(Colors.Red);
            }
            return null;
        }
    }
}


XML
<window.resources>
        <local:ColorChange x:Key="ColorChange"/>
    
    <grid>
        
        <TextBox  Text="{Binding Path=FirstName, Mode=TwoWay}" Margin="145,20,187,264" />

        
        <TextBox  Text="{Binding  Path=LastName, Mode=TwoWay}" Margin="145,75,187,209" />
        
        <TextBox Name="fulltxtname" Text="{Binding Path=FullName, Mode=TwoWay}"  Margin="145,125,187,159"/>
      
        
        <TextBox Name ="TimerCount" Text="{Binding Path=timeIndicator,Mode=TwoWay }" Margin="75,200,297,89"/>
        <Ellipse Fill="{Binding ElementName=TimerCount, Converter={StaticResource ColorChange}}" HorizontalAlignment="Left" Height="35" Margin="260,195,0,0" Stroke="Black" VerticalAlignment="Top" Width="40"/>
Posted
Updated 16-Mar-17 16:09pm
v2
Comments
[no name] 16-Mar-17 10:36am    
Probably because you are binding to timeIndicator but the actual property name is TimeIndicator. Those binding error messages you see in your output window are really trying to tell you something.
Member 13048543 16-Mar-17 10:55am    
I have rectified it but i am getting en error 'DynamicValueConverter' failed to convert value 'System.Windows.Controls.TextBox'(Type String).
[no name] 16-Mar-17 11:13am    
That is because you are trying to convert a System.Windows.Controls.TextBox control in your converter just like you told it to do.
Member 13048543 16-Mar-17 11:21am    
Thank you very much. I have added Converter={StaticResource ColorChange} in timer text box then it is showing the time.But my requirement is whenever timer event arises the ellipse color has to change.Please can you give me any suggestion?
[no name] 16-Mar-17 11:52am    
So in your timer event, change the color and notify the UI that a change has occurred. hint: that is what OnNotifyPropertyChanged does.

1 solution

Here is a demo of how to set it up (yes I don't use a timer, but the same principle applies):

Set up notification base


Encapsulate common code.
C#
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace WpfBindingEvents
{
    public abstract class ObservableObject : INotifyPropertyChanged
    {
        public void Notify([CallerMemberName] string caller = "")
        {
            PropertyChanged?.Invoke(this,
                new PropertyChangedEventArgs(caller));

        }
        public event PropertyChangedEventHandler PropertyChanged;
    }
}

Model


C#
namespace WpfBindingEvents
{
    public class Person: ObservableObject
    {
        private string firstName;
        public string FirstName
        {
            get { return firstName; }
            set
            {
                firstName = value;
                Notify();
                SetFullName();
            }
        }

        private string lastName;
        public string LastName
        {
            get { return lastName; }
            set
            {
                lastName = value;
                Notify();
                SetFullName();
            }
        }

        private string fullName;
        public string FullName
        {
            get { return fullName; }
            private set
            {
                fullName = value;
                Notify();
            }
        }

        private void SetFullName()
        {
            FullName = firstName + " " + lastName;
        }
    }
}

ViewModel


C#
namespace WpfBindingEvents
{
    public class MainViewModel : ObservableObject
    {

        public MainViewModel()
        {
            Model.PropertyChanged += ModelPropertyChanged;
        }

        private void ModelPropertyChanged(object sender, 
                                          PropertyChangedEventArgs e)
        {
            HasFullName = !string.IsNullOrEmpty(Model.FullName);
        }

        public Person Model { get; } = new Person();

        private bool hasFullName;
        public bool HasFullName
        {
            get { return hasFullName; }
            set
            {
                hasFullName = value;
                Notify();
            }
        }
    }
}

ValueConverter


C#
using System;
using System.Globalization;
using System.Windows.Data;
using System.Windows.Media;

namespace WpfBindingEvents
{
    public class ValidationColorConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return new SolidColorBrush((bool)value ? Colors.Green : Colors.Red);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

Xaml Page


XML
<Window x:Class="WpfBindingEvents.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:WpfBindingEvents"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Window.DataContext>
        <local:MainViewModel/>
    </Window.DataContext>
    <Window.Resources>
        <local:ValidationColorConverter x:Key="ValidationColorConverter"/>
    </Window.Resources>
    <Grid HorizontalAlignment="Center" VerticalAlignment="Center">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <TextBlock Text="First Name:" Margin="10 5"/>
        <TextBox Text="{Binding Model.FirstName, Mode=TwoWay, 
                                UpdateSourceTrigger=PropertyChanged}" 
                 Grid.Column="1" 
                 Width="200" VerticalAlignment="Center"/>

        <TextBlock Text="Last Name:" Grid.Row="1" Margin="10 5"/>
        <TextBox Text="{Binding Model.LastName, Mode=TwoWay, 
                                UpdateSourceTrigger=PropertyChanged}" 
                 Grid.Row="1" Grid.Column="1" 
                 Width="200" VerticalAlignment="Center"/>

        <TextBlock Text="Full Name:" Grid.Row="2" Margin="10 0"
                   VerticalAlignment="Center"/>
        <Border BorderThickness="1" 
                BorderBrush="{Binding HasFullName, 
                                      Converter={StaticResource ValidationColorConverter}}" 
                Margin="0 5" Grid.Row="2" Grid.Column="1"
                HorizontalAlignment="Stretch">
            <TextBlock Text="{Binding Model.FullName}" Grid.Row="1" Margin="5"/>
        </Border>
    </Grid>
</Window>
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900