In my Windows Store App, I have a CueAnswerButton user control. It contains an Image control which binds to {Binding NormalImage} in the view model. However I have other controls and properties inside CueAnswerButton which need to be updated whenever the bound property changes (I want to execute code inside CueAnswerButton whenever it changes).
How can I do so?
I have found other articles that explain something similar, but not quite. Perhaps I don’t know the right terminology to use to find the answer.
Thanks for your help.
// View data model for a cue answer button.
public class CueAnswerViewData : DependencyObject
{
public CueAnswerViewData()
{
}
public const string NormalImagePropertyTag = "NormalImageProperty";
public static readonly DependencyProperty NormalImageProperty =
DependencyProperty.Register(
NormalImagePropertyTag,
typeof(ImageSource),
typeof(CueAnswerViewData),
new PropertyMetadata(null));
public ImageSource NormalImage
{
get
{
return (ImageSource)GetValue(
NormalImageProperty);
}
set
{
SetValue(NormalImageProperty, value);
}
}
and the CueAnswerButton.xaml:
<Grid>
<Button x:Name="m_button"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
BorderThickness="0"
/>
<Image x:Name="m_image"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Stretch="Fill"
Source="{Binding NormalImage}"
/>
...
Basically I want to call CueAnswerButton.updateSkinnableProperties() whenever the NormalImage property on the ViewData changes. Yes this is a port of a wp7 app :), and it is still a work in progress.
private void updateSkinnableProperties()
{
bool skinned = isSkinned();
m_image.IsHitTestVisible = skinned;
m_button.IsHitTestVisible = !skinned;
Background = m_correctHint ? m_correctAnswerGreenBrush : null;
m_textbox.Background = m_correctHint ? m_correctAnswerGreenBrush : null;
m_button.Background = m_correctHint ? m_correctAnswerGreenBrush :
m_phoneBackgroundBrush;
m_button.BorderThickness = (skinned || m_correctHint) ?
m_zeroThickness : m_phoneBorderThickness;
m_textbox.Foreground = (skinned || m_correctHint) ?
m_blackBrush : m_phoneForegroundBrush;
m_button.Padding = skinned ?
m_zeroThickness : m_phoneTouchTargetOverhang;
if (!skinned)
{
m_button.Content = null;
}
updateSkinnableStateBasedProperties();
}
public bool isSkinned()
{
bool skinned = false;
if (m_normalImage != null && m_normalImage.ToString().Length > 0)
{
skinned = true;
}
return skinned;
}
private void updateSkinnableStateBasedProperties()
{
if (!m_correctHint && isSkinned())
{
m_image.Visibility = Visibility.Visible;
if (m_pressed && m_pressedImage != null)
{
m_image.Source = m_pressedImage;
}
else
{
m_image.Source = m_normalImage;
}
}
else
{
m_image.Source = null;
if(!m_correctHint)
{
m_textbox.Foreground = m_pressed ?
m_phoneBackgroundBrush : m_phoneForegroundBrush;
m_button.Background = m_pressed ?
m_phoneForegroundBrush : m_phoneBackgroundBrush;
}
}
}
Giving +1’s to Jeff Brand, as his answers helped me find my solution. However, the best way to solve this was to stop trying to fight the system and move the updateSkinnableProperties() logic into the ViewModel itself, and have it implement INotifyPropertyChanged. Some of the properties it exposes are more UI-centric rather than Data-centric (such as Brush and Thickness properties), but ultimately this was the cleanest and best solution.
Thanks!