2013-01-04 106 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