This is a follow up for these two questions here. I have a custom user control that is designed to allow users to adjust a colors A, R, G and B channels :
Each of these sliders controls one aspect of the color by the Color.FromScRgb
method.
Each slider runs from 0 to 1.
I have implemented a class to handle the input from the control - a Color View Model class:
public class ColorViewModel : INotifyPropertyChanged {
public event PropertyChangedEventHandler PropertyChanged;
private Color _Color = Colors.Black;
public double A {
get { return this.Color.ScA; }
set {
this._Color.ScA = ( float )value;
if ( this.PropertyChanged != null ) {
this.PropertyChanged( this, new PropertyChangedEventArgs( "A" ) );
this.PropertyChanged( this, new PropertyChangedEventArgs( "Color" ) );
}
}
}
public double R {
get { return this.Color.ScR; }
set {
this._Color.ScR = ( float )value;
if ( this.PropertyChanged != null ) {
this.PropertyChanged( this, new PropertyChangedEventArgs( "R" ) );
this.PropertyChanged( this, new PropertyChangedEventArgs( "Red" ) );
this.PropertyChanged( this, new PropertyChangedEventArgs( "Color" ) );
}
}
}
public double G {
get { return this.Color.ScG; }
set {
this._Color.ScG = ( float )value;
if ( this.PropertyChanged != null ) {
this.PropertyChanged( this, new PropertyChangedEventArgs( "G" ) );
this.PropertyChanged( this, new PropertyChangedEventArgs( "Green" ) );
this.PropertyChanged( this, new PropertyChangedEventArgs( "Color" ) );
}
}
}
public double B {
get { return this._Color.ScB; }
set {
this._Color.ScB = ( float )value;
if ( this.PropertyChanged != null ) {
this.PropertyChanged( this, new PropertyChangedEventArgs( "B" ) );
this.PropertyChanged( this, new PropertyChangedEventArgs( "Blue" ) );
this.PropertyChanged( this, new PropertyChangedEventArgs( "Color" ) );
}
}
}
public Color Color {
get { return this._Color; }
set {
this._Color = value;
if ( this.PropertyChanged != null )
this.AllChanged( );
}
}
public Color Red { get { return Color.FromScRgb( 1.0F, ( float )this.R, 0.0F, 0.0F ); } }
public Color Green { get { return Color.FromScRgb( 1.0F, 0.0F, ( float )this.G, 0.0F ); } }
public Color Blue { get { return Color.FromScRgb( 1.0F, 0.0F, 0.0F, ( float )this.B ); } }
private void AllChanged( ) {
this.PropertyChanged( this, new PropertyChangedEventArgs( "A" ) );
this.PropertyChanged( this, new PropertyChangedEventArgs( "R" ) );
this.PropertyChanged( this, new PropertyChangedEventArgs( "G" ) );
this.PropertyChanged( this, new PropertyChangedEventArgs( "B" ) );
this.PropertyChanged( this, new PropertyChangedEventArgs( "Red" ) );
this.PropertyChanged( this, new PropertyChangedEventArgs( "Green" ) );
this.PropertyChanged( this, new PropertyChangedEventArgs( "Blue" ) );
this.PropertyChanged( this, new PropertyChangedEventArgs( "Color" ) );
}
}
The communication works well - Any time I adjust the control settings, I can see it reflected in the CVM class. This is great, but it does not help me, as I need a way to access the color from the CVM class. I use an instance of the CVM class as a data context for the control, and then I try to bind a custom property in the Control to the controls Data Context, but it does not seem to be working :
Here is a part of the XAML :
<UserControl
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:Components="clr-namespace:WPFTools.Components"
xmlns:Controls="clr-namespace:WPFTools.Controls"
x:Class="WPFTools.Controls.ColorDefiner"
mc:Ignorable="d"
Width="120" Height="109.25" FontFamily="Arial" FontWeight="Bold">
<UserControl.DataContext>
<Controls:ColorViewModel/>
</UserControl.DataContext>
This is the control class code (I can provide the XAML if anyone feels it would be necessary, but for now I will leave it out - as it is quite verbose) -
public partial class ColorDefiner : UserControl {
public static readonly DependencyProperty
_Color = DependencyProperty.Register( "Color", typeof( Color ), typeof( ColorDefiner ) );
public Color Color {
get { return ( Color )this.GetValue( ColorDefiner._Color ); }
set { this.SetValue( ColorDefiner._Color, value ); }
}
private ColorViewModel CVM { get { return this.DataContext as ColorViewModel; } }
public ColorDefiner( ) {
InitializeComponent( );
//There is no error here, but it seems that the color is not being set in the Color property of this control!
Binding B = new Binding( "Color" ) { Source = this.DataContext, Mode = BindingMode.TwoWay };
this.SetBinding( ColorDefiner._Color, B );
}
}
I put a break point on the Set Color Property but it does not get hit when I adjust one of the sliders.
Am I implementing the MVVM properly here? Why is the CVM not updating the ColorDefiner Color Property?
EDIT
It was suggested I could tie into the DataContextChanged event - this did not work.
public ColorDefiner( ) {
this.DataContextChanged += ( S, E ) => {
Binding B = new Binding( "Color" ) { Source = this.DataContext, Mode = BindingMode.TwoWay };
this.SetBinding( ColorDefiner._Color, B );
};
InitializeComponent( );
}
I tried once with the event below the InitializeComponent but the call order was wrong, the event never fired. In this fashion, the event fired, but the CVM is still not setting the dependency property. Also; I do not think this is the issue, as if it was, then the DataContext would have been null and an exception should have been thrown (I think).