2013-01-04 105 views
1

在我的Windows应用商店中,我有一个CueAnswerButton用户控件。它包含一个Image控件,该控件绑定到视图模型中的{Binding NormalImage}。然而,在CueAnswerButton中有其他控件和属性,当绑定属性发生变化时(我想在CueAnswerButton内部执行代码时,只要它发生变化)就需要更新它们。处理UserControl属性的正确方法?

我该怎么做?

我发现other articles可以解释类似的情况,但并不完全。也许我不知道使用正确的术语来找到答案。

感谢您的帮助。

// 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); 
    } 
    } 

和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}" 
      /> 

    ... 

基本上,我想打电话给CueAnswerButton.updateSkinnableProperties()每当在ViewData的变化NormalImage财产。是的,这是一个WP7应用程序的端口:),它仍然是一个正在进行的工作。

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; 
    } 
    } 
} 

回答

0

给予+ 1名的杰夫品牌,他的回答帮我找到了我的解决方案。然而,解决这个问题的最好方法是停止尝试打击系统并将updateSkinnableProperties()逻辑移入ViewModel本身,并使其实现INotifyPropertyChanged。它公开的一些属性更多的是以UI为中心而不是以数据为中心的属性(比如Brush和Thickness属性),但最终这是最干净和最好的解决方案。

谢谢!

1

您可以添加一个被调用的每次改变DependecyProperty值代表...

public static readonly DependencyProperty NormalImageProperty = 
    DependencyProperty.Register(
     NormalImagePropertyTag, 
     typeof(ImageSource), 
     typeof(CueAnswerViewData), 
     new PropertyMetadata(null, (s, e) => 
       var ctrl = s as CueAnswerViewData; 
       if (ctrl != null) { 
        ctrl.somePropertyToUpdate = 123; 
       } 
      }) 
      ); 
+0

谢谢,但不是视图模型了解视图类型的坏设计吗? – swinefeaster

+0

抱歉抱歉。忘记了我们在谈论视图模型。在CueAnswerButton中,你难道不能将其他控件绑定到NormalImage以及对更新后的属性作出反应,还是错过了某些东西? –

+0

不容易,因为我需要为所有内容编写复杂的转换器。我会在一秒内用这段代码更新这个问题,所以你知道我的意思。我可以定义一些接口,如ICueAnswerNormalImageChanged,从它派生我的CueAnswerButton类,并使用上面的解决方案。但似乎应该有一种方法来与现有机制做到这一点?再次感谢你的帮助。 – swinefeaster