2012-02-26 9 views
0

私は以下のようなクラス構造を持っています。今Bindingソースとして「Get Only」静的プロパティを使用する

//On the design aspects, I know It may not be the advisable approach, 
//but something of this kind is only required. 

/// <summary> 
/// Paper Class 
/// </summary> 
public class Paper 
{ 
    public string PaperName { get; set; } 
    public bool IsPending { get; set; } 
} 

/// <summary> 
/// PaperChecking class, Individual papers will be processed here. 
/// </summary> 
public class PaperChecking 
{ 

    public static List<Paper> ListPapers { get; set; } 

    public static void AddPapers() 
    { 
     ListPapers = new List<Paper>(); 

     ListPapers.Add(new Paper() { PaperName = "Paper1", IsPending = false }); 
     ListPapers.Add(new Paper() { PaperName = "Paper2", IsPending = false }); 
     ListPapers.Add(new Paper() { PaperName = "Paper3", IsPending = false }); 
     ListPapers.Add(new Paper() { PaperName = "Paper4", IsPending = false }); 
     ListPapers.Add(new Paper() { PaperName = "Paper5", IsPending = false }); 
    } 

    public static bool IsCheckingPending 
    { 
     get 
     { 
      //List has items and it is not null, so intentionally removed the checks. 
      return ListPapers.Count(paper => paper.IsPending == true) > 0 ? true : false; 
     } 
    } 
} 

/// <summary> 
/// This class will select papers for processing 
/// </summary> 
public class ChangePaperSetting 
{ 
    public void SelectPaper(string paperName) 
    { 
     //It can be assumed that Paper object will never be NULL 
     PaperChecking.ListPapers.FirstOrDefault(paper => paper.PaperName.Equals(paperName)).IsPending = true; 

    } 
} 

、 私は私のWPFウィンドウにいくつかのコントロールを表示するには、プロパティPaperChecking.IsCheckingPendingを使用します。同じプロパティをコントロールのVisibilityにバインドしました。最初にウィンドウが読み込まれるときに、Collectionが既に存在するため、動作が期待されます。しかし、私は以下のようPaperオブジェクトの保留中の状態を変更しています実行時に:私のコレクションで

ChangePaperSetting changePaperSetting = new ChangePaperSetting(); 
    changePaperSetting.SelectPaper("Paper1"); 
    changePaperSetting.SelectPaper("Paper2"); 
    changePaperSetting.SelectPaper("Paper5"); 

、今私は、真IsPendingてきた書類を持っています。今、PaperChecking.IsCheckingPendingはTRUEを返し、それに応じてコントロールが表示されるはずです。

通常のオブジェクトでは、私はINotifyPropertyChangedを実装できましたが、上記のケースでは、プロパティにSetterがありません。同じ種類のクラス構造を使ってこれを行う方法や他のきちんとした方法はありますか?

//-------------------------------------------------------------------------------// 

更新

ジョシュによって示唆されるように、私はこのような何かを試してみました:ここ

/// <summary> 
/// Paper Class 
/// </summary> 
public class Paper : INotifyPropertyChanged 
{ 
    public string PaperName { get; set; } 
    private bool isPending; 

    public bool IsPending 
    { 
     get 
     { 
      return isPending; 
     } 
     set 
     { 
      if (isPending != value) 
      { 
       isPending = value; 
       PropertyChanged(this, new PropertyChangedEventArgs("IsPending")); 
      } 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
} 

/// <summary> 
/// PaperChecking class, Individual papers will be processed here. 
/// </summary> 
public class PaperChecking : Control 
{ 

    public static List<Paper> listOfPapers { get; set; } 

    public static bool IsCheckingPending 
    { 
     get 
     { 
      //List has items and it is not null, so intentionally removed the checks. 
      try 
      { 
       return listOfPapers.Count(paper => paper.IsPending == true) > 0 ? true : false; 
      } 
      catch (Exception ex) { return false; } 
     } 
    } 


    public static event PropertyChangedEventHandler PropertyChanged; 
    public static void PendingStatusChanged(object sender,PropertyChangedEventArgs e) 
    { 
     if (e.PropertyName == "IsPending") 
     {     
      //If I keep it static, It given Null Reference Error 
      //and If I implement INotifyPropertyChanged interface 
      //in this Class, it gives compilation error because 
      //I am doing so in my Static property. 

      PropertyChanged(null,new PropertyChangedEventArgs("IsCheckingPending")); 
     } 
    } 

} 

/// <summary> 
/// This class will select papers for processing 
/// </summary> 
public class ChangePaperSetting 
{ 
    public static void AddPapers() 
    { 

     var listOfPapers = new List<Paper>(); 
     for (int i = 0; i < 5; i++) 
     { 
      var paper = new Paper() { PaperName = "Paper"+i.ToString(), 
             IsPending = false }; 
      paper.PropertyChanged+=PaperChecking.PendingStatusChanged; 
      listOfPapers.Add(paper); 
     } 
     PaperChecking.listOfPapers = listOfPapers; 
    } 
    public void SelectPaper(string paperName) 
    { 
     //It can be assumed that Paper object will never be NULL 
     PaperChecking.listOfPapers.FirstOrDefault(paper => paper.PaperName.Equals(paperName)).IsPending = true; 
    } 
} 

は私のXAMLコードは次のとおりです。ここで

<Window xmlns:my="clr-namespace:LearningWpf" x:Class="LearningWpf.Window4" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window4" Height="300" Width="300"  
    > 
<Window.Resources> 
    <my:PaperChecking x:Key="paperChecking"/> 
    <BooleanToVisibilityConverter x:Key="bvc" /> 
</Window.Resources> 
<StackPanel> 
    <Button Name="btn1" Content="Button1" Height="20" Width="80" Click="btn1_Click"></Button> 
    <Button Name="btn2" Content="Button2" Height="20" Width="80" Click="btn2_Click"></Button> 
    <Button Name="btn3" Content="Button3" Height="20" Width="80" 
      Visibility="{Binding Source={StaticResource paperChecking}, 
         Path=IsCheckingPending, 
         Converter={StaticResource bvc}}"></Button> 
</StackPanel> 

は私ですCodeBehind.c s

public partial class Window4 : Window 
{ 
    public Window4() 
    { 
     InitializeComponent(); 
    } 

    private void btn1_Click(object sender, RoutedEventArgs e) 
    { 
     ChangePaperSetting.AddPapers(); 

    } 

    private void btn2_Click(object sender, RoutedEventArgs e) 
    { 
     var v = PaperChecking.listOfPapers.FirstOrDefault(paper => 
       paper.PaperName == "Paper1"); 
     v.IsPending = true; 
    } 
} 

しかし、このコードでは、初期化せずにStatic変数を使用しているので、righltyというエラーが発生しています。同じ目標を達成するための修正や他のアプローチがある場合。あなたの助けが高く評価されます。

答えて

0

トピックはありませんが、なぜPaperChecking内のすべてのプロパティと機能が静的ですか?

問題を解決するには、PaperCheckingに新しい関数を追加し、INotifyPropertyChangedを実装してください。

public void SelectPaper(string paperName) 
{ 
    var paper = ListPapers.FirstOrDefault(paper => paper.PaperName.Equals(paperName)); 
    if (paper != null) 
    { 
     paper.IsPending = true; 
     PropertyChanged("IsCheckingPending"); 
    } 
} 

私はあなたがINotifyPropertyChangedを実装し、イベントを高める独自の方法を持ってする方法を知っていると仮定しています。プロパティの設定者からイベントを呼び出さなければならないということは何もありません。

クエリが実行されるたびにプロパティゲッターサイクルをペーパーリスト全体に適用することは非常に効率が悪いです。それは非常に頻繁に呼び出すことができます。マウスやキーボードのイベントにはかなり似ています。 Paper上で保留中のステータスが変更されるたびに、カウントの値をキャッシュするようにしてください。それはもう少し作業が必要ですが、それは価値があるかもしれません。

編集:

実際のオブジェクトは、複数のインターフェースから更新することができ、それらが同じメソッドを呼び出すことはありません、彼らはPAPERオブジェクトへの参照を持っているし、プロパティを直接更新します、代わりにPaperCheckingクラスのメソッド

呼び出しますその場合

、あなたは紙の上のクラスINotifyPropertyChangedを実装する必要があり、その後、PaperChecking以内にこれらの更新を聞きます。

public void PaperChanged(object sender, PropertyChangedEventArgs args) 
{ 
    if (args.PropertyName == 'IsPending') PropertyChanged("IsCheckingPending"); 
} 

public void AddPapers() 
{ 
    ListPapers = new List<Paper>(); 

    ListPapers.Add(new Paper() { PaperName = "Paper1", IsPending = false }); 
    ListPapers.Add(new Paper() { PaperName = "Paper2", IsPending = false }); 
    ListPapers.Add(new Paper() { PaperName = "Paper3", IsPending = false }); 
    ListPapers.Add(new Paper() { PaperName = "Paper4", IsPending = false }); 
    ListPapers.Add(new Paper() { PaperName = "Paper5", IsPending = false }); 
    foreach(var paper in ListPapers) 
    { 
     paper.PropertyChanged += PaperChanged; 
    } 
} 

はまた、静的なものではなく、インスタンスメソッドとプロパティを使用するクラスにPaperCheckingを変換する必要があります。 MVVMについてまだ分かっていない場合は、reading up on itをお勧めします。基本的には、PaperCheckingのインスタンスを作成し、ビューのコードの後ろにDataSourceと設定します。次に、あなたのXAMLで、あなたは、単にこのようにバインドすることができます:WPFで出始めたときに

<Button Name="btn3" Content="Button3" Height="20" Width="80" 
    Visibility="{Binding IsCheckingPending, Converter={StaticResource bvc}}" /> 

静的プロパティとメソッドは、ほぼ常に間違っています。いつあなたがそれらを使用する必要があるか、あなたが自分で簡単に物事をしようとしているときを知ってください。

+0

実際、私はそれをやっていると思っていました。ここではプロパティを更新するインターフェイスの数が多く、オブジェクトプロパティの存続期間中に非常に頻繁に変更されるようになっています。 – AjayK

+0

実際、オブジェクトは複数のインターフェイスから更新でき、同じメソッドを呼び出さず、PAPERオブジェクトへの参照を持ち、PaperCheckingクラスのメソッドを呼び出す代わりに直接プロパティを更新します。それが事実だったのであれば、問題はむしろ単純かつ直接的な実装です。 – AjayK

+0

これはいつでもどこでも新しいPaperが追加されたときにこのハンドラを割り当てる必要があります。しかし、同じコレクションが複数のインターフェイスにまたがって更新されていますが、これはかなり難しいようです。依存関係のプロパティを使用することで、何か別の方法がありますか?ジョシュ@ – AjayK

0

あなたはCLRプロパティを使用しているので、とてもそのあなたの義務は、基礎となる結合性は、あなたのコードからPropertyChangedイベントを上げることによってのみ達成可能である変更されたUIを通知します。 まず、INotifyCollectionChangedとINotifyPropertyChangedを実装しているので、コレクションをObservableCollectionとします。あなたはこの方法から、コレクション内の項目を追加する必要がある場合は、あなたが心配する必要はありません。このアプローチでは

ObservableCollection<Paper> listOfPapers = new ObservableCollection<Paper>(); 
listOfPapers.CollectionChanged += new NotifyCollectionChangedEventHandler(listOfPapers_CollectionChanged); 

void listOfPapers_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e) 
{ 
     OnPropertyChanged("IsCheckingPending"); 
} 

- あなたのコレクションでコレクション変更イベントをフックし、ハンドラで、単にこのようなあなたのプロパティのPropertyChangedイベントを上げますSelectPaper()を除く。

他の可能な解決策は、あなたが明示的に変更されたプロパティを上げる心配する必要はありません道の代わりにプレーンなCLRプロパティの使用Dependency Propertyだったかもしれません。

http://msdn.microsoft.com/en-us/library/ms752914.aspx

+0

リストアイテムのプロパティを変更する場合は、コレクションを変更した場合のみ、これは機能しません。 –

+0

@RVええとジョシュと同じように、私はここでコレクションを変更するのではなく、構成アイテムです。私は、依存関係プロパティを使って代替案を探していました。私はそれを使用しようとしていましたが、PaperクラスまたはPaperCheckingクラスに依存プロパティを使用するかどうかは疑問があります。ご参考までにご連絡ください。援助のためのThanx。 – AjayK

0

このような何か、多分?

private static bool _isCheckingPending; 
public static bool IsCheckingPending 
{ 
    get 
    {    
     bool pending = ListPapers.Count(paper => paper.IsPending == true) > 0; 

     if (pending != _isCheckingPending) 
     { 
      PropertyChanged("IsCheckingPending"); 
      _isCheckingPending = pending; 
     } 

     //List has items and it is not null, so intentionally removed the checks. 
     return _isCheckingPending; 
    } 
} 

アイデアは、それが(そしてもちろん、あなたがINotifyPropertyChangedの実装をAVEます)前回からの結果を覚えて、それが結果から、この時間は異なる場合、PropertyChangedイベントを上げることです。

+0

しかし、静的プロパティでは、PropertyChanged Event.Anyを実装することはできません。 – AjayK

+0

そしてとりわけ、GETは誰かが値にアクセスしようとする場合にのみ呼び出されます。ここでは、基礎となるコレクションのオブジェクトが変更され、その後、それ自体が呼び出される必要があります。それが私の問題です。それが変更されたことを基になるコレクションがどのように通知するか。 – AjayK

関連する問題