2014-10-28 35 views
1

我目前正在使用MVVM(而不是MVVM Light)在C#/ XAML中開發通用應用程序,並且我在XAML部分中遇到了問題。當依賴項屬性發生變化時,StackPanel可見性未更新

我想顯示一個或另一個StackPanel當我的ViewModel中的依賴項屬性發生變化。我認爲這個代碼本身就是有說服力的。

<StackPanel Visibility="{Binding MyProperty, Converter={StaticResource BooleanToVisibilityConverter}}"> 
    <!-- Some content --> 
</StackPanel> 

<StackPanel Visibility="{Binding MyProperty, Converter={StaticResource InvertBooleanToVisibilityConverter}}"> 
    <!-- Some another content --> 
</StackPanel> 

這裏是依賴項屬性的定義。

public static readonly DependencyProperty MyPropertyProperty = DependencyProperty.Register(
    "MyProperty", 
    typeof (bool), 
    typeof (MyViewModel), 
    new PropertyMetadata(true)); 

public bool MyProperty 
{ 
    get { return (bool) GetValue(MyPropertyProperty); } 
    set { SetValue(MyPropertyProperty, value); OnPropertyChanged(); // Implemented by ReSharper } 
} 

我猜你弄明白這MyProperty是我通過轉換器轉換爲Visibility一個布爾值。所以,當在ViewModel中更改MyProperty時,視圖不會更新。

我已經嘗試使用UpdateSourceTrigger屬性,但它不起作用。此外,我沒有綁定錯誤和轉換器工作正常(我只看到一個StackPanel在應用程序啓動)。

請記住,我不想使用部分背後的代碼,除非沒有其他解決方案。

感謝您的幫助。

+0

您可以添加您的依賴屬性的定義嗎? – 2014-10-28 20:11:48

+0

你通知財產改變了嗎? – 2014-10-28 20:14:19

+0

@AaronHawkins:當然。我剛剛編輯了首發帖子。 – Atlasmaybe 2014-10-28 20:41:55

回答

1

我finaly放棄了,用後面的代碼部分,現在工作正常。

0

您的<StackPanel>是某個UserControl的一部分嗎?如果不是,你爲什麼使用DependencyProperty

你的實現也是相當不錯的。

讓我們假設一分鐘,這不是一個自定義控件的一部分(糾正我 - 如果我錯了,我將改寫溶液)

所以,你有一個視圖模型,你想掛鉤它的一些屬性。你實際上不需要實現DependencyProperty來做你想做的事情,但我會通過你的方式來實現它。

這是1(一)財產的樣本視圖模型

using Windows.UI.Xaml; 
using System.ComponentModel; 

// very simple view model 
class MyViewModel : DependencyObject, INotifyPropertyChanged 
{ 

    // implement INotifyPropertyChanged 
    public event PropertyChangedEventHandler PropertyChanged; 
    protected void OnPropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    // register 
    public static DependencyProperty FooterTitleProperty = DependencyProperty.Register("FooterTitle", typeof(string), typeof(MyViewModel), 
     new PropertyMetadata(string.Empty, OnFooterTitlePropertyChanged)); 

    // the actual property 
    public string FooterTitle 
    { 
     get { return (string) GetValue(FooterTitleProperty); } 
     set 
     { 
      SetValue(FooterTitleProperty, value); 
     } 
    } 

    // this will fire when the property gets change 
    // it will call the OnPropertyChanged to notify the UI element to update its layout 
    private static void OnFooterTitlePropertyChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) 
    { 
     MyViewModel mvm = dependencyObject as MyViewModel; 
     mvm.OnPropertyChanged("FooterTitle"); 
    } 
} 

爲了測試代碼,我們將做一個非常簡單的XAML形式

<Grid x:Name="ContentPanel"> 
    <StackPanel> 
     <TextBlock x:Name="tb" Text="{Binding FooterTitle}" FontSize="48"></TextBlock> 
     <Button Content="Test Property" Click="Button_Click_1"></Button> 
    </StackPanel> 
</Grid> 

當你點擊按鈕我們將更改文本框的文本

public sealed partial class MainPage : Page 
{ 
    // create the view model 
    MyViewModel vm = new MyViewModel(); 

    public MainPage() 
    { 
     this.InitializeComponent(); 

     this.NavigationCacheMode = NavigationCacheMode.Required; 


     // set the text we initial want to display 
     vm.FooterTitle = "default text"; 

     // set the DataContext of the textbox to the ViewModel 
     tb.DataContext = vm; 
    } 


    // after the button is click we change the TextBox's Text 
    private void Button_Click_1(object sender, RoutedEventArgs e) 
    { 
     // change the text 
     vm.FooterTitle = "Test Property Has Changed."; 

     // what happens is the Setter of the Property is called first 
     // after that happens it launches the `OnFooterTitlePropertyChanged` event 
     // that we hook up with the Register function. 


     // `OnFooterTitlePropertyChanged` launches the INotifyPropertyChanged event 
     // then finally the TextBox will updates it's layout 
    } 
} 

在這一點上,你可以猜到你真的不需要DependencyProperty,並說爲什麼我不能在Setter中啓動INotifyPropertyChanged呢?那麼你可以,它可能是更喜歡的方法。

如果所有這些是用戶控件的一部分,那麼我可以看到使用的DependencyProperty然後在OnFooterTitlePropertyChanged事件中,你可以設置

name_of_textbox.Text = FooterTitle; 
+0

感謝您的回答,但那不是我要找的。 現在我的'StackPanel'不是自定義的'UserControl'的一部分,但是他們會晚點(我處於開發的早期階段)。另外,我想避免使用代碼背後的代碼,因爲它是一個通用應用程序,我不想複製/粘貼代碼。當然,如果有其他解決方案,我會照你說的去做。 – Atlasmaybe 2014-10-29 08:27:51

+0

@Atlasmaybe沒有代碼背後(這只是測試虛擬機)。該VM可以是共享項目的一部分。用你的StackPanel替換TextBox,你會看到一旦你的Property改變它將啓動你的轉換器。我編碼的例子是讓你進入正確的方向,因爲你的問題和示例代碼沒什麼意義。 – 2014-10-29 09:10:20

+0

我分析了你的代碼,它和我的代碼一樣:你有一個簡單的虛擬機和一個DP,一個簡單的View。差異在於OnPropertyChanged()事件啓動和ButtonClickEvent(它是您創建的頁面背後的代碼的一部分),您用它來更改屬性,而在VM中更改我的屬性。 我很欣賞你給我的「正確方向」所付出的努力,但如果我們有相同的代碼,我認爲這不會有幫助。 – Atlasmaybe 2014-10-29 09:45:13

相關問題