2016-09-23 5 views
0

私はちょうどC#の初心者です。私はMSDNブログのINotifyPropertyChanged Event Handlerについて読んで、ここで "stackoverflow"を検索しました。しかし、私は自分のコードでそれを実装する方法と、イベントとプロパティをどのように束縛しなければならないのかを本当に理解していません。
CantはINotifyPropertyChangedの実装を理解しています

私はすでにINotifyPropertyChangedBindingClassをしたし、コードは次のとおりです。

namespace Testing.Pages 
{ 
    class BindingClass : INotifyPropertyChanged 
    { 
    private string _setting; 
    public event PropertyChangedEventHandler PropertyChanged; 

    public BindingClass() 
    { 

    } 

    public BindingClass(string value) 
    { 
     _setting = value; 
    } 

    public string SettingProperty 
    { 
     get { return _setting; } 
     set 
     { 
      _setting = value; 
      // calling OnPropertyChanged whenever the property gets updated 

     } 
    } 

    protected void OnPropertyChanged([CallerMemberName] string _setting = "") 
    { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(_setting)); 
    } 
    } 
} 


SettingsPage.xaml

<TextBlock x:Name="PopupText" 
       Grid.Row="0" 
       HorizontalAlignment="Center" 
       VerticalAlignment="Center" 
       Margin="0,0,0,20" 
       Text="Your theme will be updated next time you start the app." 
       TextWrapping="Wrap" 
       Visibility="Collapsed"> 
     <TextBlock.Resources> 
      <Storyboard x:Name="popup_animate"> 
       <DoubleAnimation Duration="0:0:2" 
           Storyboard.TargetName="PopupText" 
           AutoReverse="True" 
           From="0.0" 
           To="1.0" 
           BeginTime="{x:Bind }" 
           Storyboard.TargetProperty="(TextBlock.Opacity)" 
         ></DoubleAnimation> 
      </Storyboard> 
     </TextBlock.Resources> 
    </TextBlock> 
<TextBlock Text="Change Theme?" 
        Margin="10,10,0,0"></TextBlock> 
     <RadioButton x:Name="DarkTheme_btn" 
        Click="ChangeTheme_btn_Click" 
        Content="Dark Theme" 
        Margin="10,0,0,0" 
        GroupName="theme"></RadioButton> 
     <RadioButton x:Name="LightTheme_btn" 
        Click="ChangeTheme_btn_Click" 
        Content="Light Theme" 
        Margin="10,0,0,0" 
        GroupName="theme"></RadioButton> 

とコードビハインドファイルSettingsPage.xaml.csは次のとおりです。

namespace Testing.Pages 
{ 

/// <summary> 
/// An empty page that can be used on its own or navigated to within a Frame. 
/// </summary> 
    public sealed partial class SettingsPage : Page 
    { 
    BindingClass notifyProperty = new BindingClass(); 

    public SettingsPage() 
    { 
     this.InitializeComponent(); 
     NavigationCacheMode = NavigationCacheMode.Enabled; 
    } 

    private void ChangeTheme_btn_Click(object sender, RoutedEventArgs e) 
    { 
     DataContext = notifyProperty; 
     int notifySettings = 0; 
     if ((bool)DarkTheme_btn.IsChecked) 
     { 
      notifySettings = 2; 
      AppSettings.saveThemeSettings(notifySettings); 
      PopupText.Visibility = Visibility.Visible; 
      popup_animate.Begin(); 
     } 
     else if ((bool)LightTheme_btn.IsChecked) 
     { 
      notifySettings = 1; 
      AppSettings.saveThemeSettings(notifySettings); 
      PopupText.Visibility = Visibility.Visible; 
      popup_animate.Begin(); 
     } 
    } 
    } 
} 

私はすでにLocalSettingsFolderにアプリの設定を変更するint notifySettingsを使用していますし、アプリ上のすべての時間は、それがApp.xamlの設定をロードして再起動します。私が設定を変更するたびに、別のclassの関数を呼び出して、設定を変更します。そして、radiobuttonsSettingsPage.xamlに2つ1つクリックすると、animationが再生されます。これは古い方法です。
Theme Settingsが更新されるたびに、int notifySettingsPopupTextのアニメーションを再生する必要がないように、これらのイベントをまとめてバインドします。これは私がINotifyPropertyChanged Eventについて学ぶ方法です。
int notifySettingsには、intの値が渡され、それに応じて設定が変更されます。 1 = LightThemeおよび2 = DarkTheme。ここで

Settings Classです:

namespace Testing.Pages 
{ 
    class AppSettings 
    { 
    public static void saveThemeSettings(int value) 
    { 
     ApplicationDataContainer themeSettings = ApplicationData.Current.LocalSettings; 
     StorageFolder localFolder = ApplicationData.Current.LocalFolder; 
     themeSettings.Values["AppThemeSetting"] = value.ToString(); 
    } 

    public static string readThemeSettings() 
    { 
     ApplicationDataContainer localSettings = ApplicationData.Current.LocalSettings; 
     StorageFolder localFolder = ApplicationData.Current.LocalFolder; 
     string appSettingsString = "error, nothing found"; 
     if (localSettings.Values.ContainsKey("AppThemeSetting")) 
     { 
      appSettingsString = localSettings.Values["AppThemeSetting"]?.ToString(); 
     } 
     return appSettingsString; 
    } 

    public static void removeLocalSettings(string settingValue) 
    { 
     ApplicationData.Current.LocalSettings.Values.Remove(settingValue); 
    } 

    } 

} 

任意のあいまいさは私が知っていると私はさらに説明しようとすることができますしてくださいまだある場合。私は誰かが私にこれを助けることを願っています。

更新:
私はダニーBogersによって答えに応じて私のプロジェクトに変更を加えたが、必要なAnimationが起動しないと私は機能をしても呼び出されていないので、それはあると思います。私はいくつかの変更を加えて自分でやろうとしましたが、実際にはうまくいきませんでしたので、自分のメソッドを使って他の誰かが解決策を見つけるまで変更を行います。

+0

プロパティを更新するたびにOnPropertyChangedを呼び出すと、そのコードを実際に表示する必要がありますか、または実際のコードにそのコメントがありますか? –

+0

私は実際にマイクロソフトのブログからコードを得て、それを少し編集しました。しかし、私はこれらの機能を一緒に実装する方法を知る必要があります。だから私はそれについて学ぶことができます。 – Ahmar

答えて

1

にPropertyChangedはが変更されたプロパティを知っている必要があるので、あなたはそれの名前を渡す必要があります。

それは次のようになり行います

public string SettingProperty 
{ 
    get { return _setting; } 
    set 
    { 
     if(_setting != value) // Or String.Equals(_setting, value, ...) 
     { 
      _setting = value; 
      OnPropertyChanged(); // Invoke using no argument. 
     } 
    } 
} 

protected void OnPropertyChanged([CallerMemberName] string propertyName = "") 
{ 
    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); 
} 

OnPropertyChangedをする方法も任意であり、そのパラメータにCallerMemberName属性を使用しています。つまり、コンパイラはこの引数を使用し、iithを呼び出し元の実際の名前に置き換えます。だからあなた自身の価値を渡してはいけません。

PropertyChanged("SettingProperty")と同等です。しかし、この属性は屈折器にとって安全です。

質問の残りの部分について:私は、質問自体があまりにも持ち込まれていて、少なくとも1つ以上の文章から構成されていることを信じています。だから、あなたはpropertychanged部分を修正して、むしろ特定の問題の新しい質問をしました。

+0

'SettingProperty'を別の場所から更新する必要がありますか?あるいは、 '_setting'の値を渡す必要がありますか? – Ahmar

+0

@Ahmar SettingProperty。それは明らかに_settingへの変更を通知しません。あなたが_settingをdirechtlyで更新したい場合は、その後、OnPropertyChanged(nameof(SettingProperty));を手動で呼び出してください。 – CSharpie

+0

ありがとう、 'OnPropertyChanged()'は実際には機能していませんでした。 – Ahmar

1

私は物事を説明するのに最高ではありません、私はあなたがそれの要点を得ることを願っています! 私はそれを正しくテストする時間がなかったが、これは仕事をするべきである。

+=の構文でイベントを購読することができます。今、イベントが発生するたびに、すべてのサブスクライバが指定された引数で起動されます。この場合、PropertyChangedEventArgsのインスタンス。これにより、ユーザはEventArgsの値に応じて異なる動作をすることができます(EventArgsの空のインスタンスをユーザに渡すことができます。つまり、ユーザはEventArgsの値に基づいて何もしません)。

いくつかのマイナーな変更:

  • がテーマの列挙型を追加しました。どのテーマが選択されているかをチェックするときに型の安全性を追加します。これは、ハードコーディングされた文字列をチェックするよりも優れています。

  • ThemeSettingが見つからない場合は例外が追加されました。それに応じてtry/catchブロックで例外を処理できます。これは、ハードコーディングされた文字列をチェックするよりも優れています。

  • appsettingキーのconst文字列を追加しました。これは、前の2つのポイントと同様に、タイプミスによるランタイムエラーを防ぎ、値を管理する中心的な場所を1つ与えます。

    namespace Testing.Pages 
    { 
        public enum Themes 
        { 
         Light = 1, 
         Dark = 2 
        } 
    } 
    
    namespace Testing.Pages 
    { 
        public class ThemeSettingNotFoundException : Exception 
        { 
         public ThemeSettingNotFoundException() : base("error, nothing found") 
         { 
         } 
        } 
    
    } 
    
    namespace Testing.Pages 
    { 
        class BindingClass : INotifyPropertyChanged 
        { 
         private string _setting; 
         public event PropertyChangedEventHandler PropertyChanged; 
    
         public BindingClass() { 
    
         } 
    
         public BindingClass(string value) { 
          _setting = value; 
         } 
    
         public string SettingProperty 
         { 
          get { return _setting; } 
          set 
          { 
           if(!_setting.Equals(value)){ 
            _setting = value; 
            OnPropertyChanged(); 
           } 
          } 
         } 
    
         protected void OnPropertyChanged([CallerMemberName] string _setting = "") { 
          PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(_setting)); 
         } 
        } 
    } 
    
    
    namespace Testing.Pages 
    { 
    
        /// <summary> 
        /// An empty page that can be used on its own or navigated to within a Frame. 
        /// </summary> 
        public sealed partial class SettingsPage : Page 
        { 
         BindingClass notifyProperty = new BindingClass(); 
    
         public SettingsPage() { 
          this.InitializeComponent(); 
          NavigationCacheMode = NavigationCacheMode.Enabled; 
    
          //Subscribe to the PropertyChanged event 
          notifyProperty.PropertyChanged += OnThemeSettingChanged; 
         } 
    
         private void ChangeTheme_btn_Click(object sender, RoutedEventArgs e) { 
          DataContext = notifyProperty; 
          SaveThemeSettings(); 
         } 
    
         private void SaveThemeSettings() 
         { 
          var notifySettings = 0; 
          if ((bool)DarkTheme_btn.IsChecked) 
           notifySettings = 2; 
          else if ((bool)LightTheme_btn.IsChecked) 
           notifySettings = 1; 
    
          //Only save theme settings when a button was checked 
          if (notifySettings != 0) 
           AppSettings.saveThemeSettings((Themes)notifySettings); 
         } 
    
         private void OnThemeSettingChanged(object sender, PropertyChangedEventArgs args) 
         { 
          PopupText.Visibility = Visibility.Visible; 
          popup_animate.Begin(); 
         } 
        } 
    } 
    
    
    namespace Testing.Pages 
    { 
        class AppSettings 
        { 
         private const string ThemeSettingKey = "AppThemeSetting"; 
    
         public static void saveThemeSettings(Themes theme) { 
          ApplicationDataContainer themeSettings = ApplicationData.Current.LocalSettings; 
          themeSettings.Values[ThemeSettingKey] = theme.ToString(); 
         } 
    
         public static Themes readThemeSettings() { 
          ApplicationDataContainer localSettings = ApplicationData.Current.LocalSettings; 
          if (!localSettings.Values.ContainsKey(ThemeSettingKey)) 
           throw new ThemeSettingNotFoundException(); 
          var appSettingsString = localSettings.Values[ThemeSettingKey]; 
          return (Themes)Enum.Parse(typeof(Themes), appSettingsString); 
         } 
    
         public static void removeLocalSettings(string settingValue) { 
          ApplicationData.Current.LocalSettings.Values.Remove(settingValue); 
         } 
        } 
    } 
    
+0

あなたのSettingPropertyセッターでは、高価なので、誤ったコードがOnPropertyChanged()をオーバーコールしないように、if(_setting!= value)チェックを追加する必要があります。 – SledgeHammer

+0

私はあなたの答えに上記の変更を実装しましたが、うまくいきません。テーマ設定が変更されても、アニメーションは実行されません。 – Ahmar

+0

実装が間違っています、OnPropertyChangedEventArgsは渡されたプロパティの名前を必要とし、任意の値ではありません。なぜそれの実装はCallerMemberNameとオプションの文字列を使用しているのですか?このOnPropertyChanged()のように呼び出すだけです。 – CSharpie

関連する問題