8

C#2010でPro WPFを読んでいる間、著者は次のように書いています。

「プロパティごとにイベントを発生させることができます。この場合、イベントの名前はPropertyNameChanged(たとえば、UnitCostChanged)である必要があります。プロパティが変更されたときにイベントを発生させるのはあなた次第です。」

誰かがこの機能が機能することを確認できますか?私は実験していて、この動作を再現できませんでした(これが機能するかどうかを確認したいので、System.Reflection.Emitを使用して動的タイプを作成できます)

編集:ここで強調するのは、INotifyPropertyChangedを実装せずに変更通知を実装することです。これは、本が主張していることです。

これが私がテストしているPOCOです:

public class Employee
{
    private string _FirstName;
    public string FirstName 
    {
        get
        {
            return _FirstName;
        }
        set
        {
            if (_FirstName != value)
            {
                _FirstName = value;
                if (FirstNameChanged != null) 
                {
                    FirstNameChanged(this, new PropertyChangedEventArgs("FirstName"));
                }
            }
        }
    }
}

これをDataGridにバインドし、バックグラウンドでタイマーを使用してFirstNameプロパティを数秒ごとにランダムに更新しましたが、DataGridが起動することはありません

<DataGrid x:Name="dgEmployees" ItemsSource="{Binding ElementName=mainWindow, Path=MyEmployees}">
        <DataGrid.Columns>
            <DataGridTextColumn Header="FirstName" Binding="{Binding Path=FirstName}" />
        </DataGrid.Columns>
    </DataGrid>

FirstNameChangedイベントは常にnullです(命名規則に従って検出された場合、バインディングエンジンが自動的にサブスクライブする可能性があると思いました)。MyEmployeesは単なるObservableCollectionです

誰かがこの機能が作者が言及しているかどうか、実際に機能しているかどうか、そして私が間違いを犯しているかどうかを確認できますか?

編集:私がテキストを誤解していると思う人のために:

「この問題を解決するには、次の3つのアプローチを使用できます。

第4章で学習した構文を使用して、Productクラスの各プロパティを依存関係プロパティにすることができます(この場合、クラスはDependencyObjectから派生する必要があります)。 )、それは要素、つまりウィンドウに視覚的に見えるクラスで最も意味があります。これは、Productのようなデータクラスにとって最も自然なアプローチではありません。

プロパティごとにイベントを発生させることができます。この場合、イベントの名前はPropertyNameChanged(たとえば、UnitCostChanged)である必要があります。プロパティが変更されたときにイベントを発生させるのはあなた次第です。

System.ComponentModel.INotifyPropertyChangedインターフェイスを実装できます。これには、PropertyChangedという名前の単一のイベントが必要です。次に、プロパティが変更されるたびにPropertyChangedイベントを発生させ、プロパティ名を文字列として指定して、変更されたプロパティを示す必要があります。プロパティが変更されたときにこのイベントを発生させるのはあなた次第ですが、プロパティごとに個別のイベントを定義する必要はありません。」

4

3 に答える 3

10

質問の要点を完全に見逃していない限り、INotifyPropertyChangedまたは本で主張されているような依存関係プロパティを使用せずにPOCOに変更通知を実装することは非常に可能だと思います。

プロパティの値が変更されたときにPOCOから{Propertyname} Changedというイベントを発生させると、WPFバインディングシステムがそれを取得し、関連するバインディングを更新します。

デモについては、この小さなプログラムを参照してください。これは私が考えることができる最も簡単なことですが、あなたの場合にも機能するはずです。

XAML:

<StackPanel>
    <TextBlock Text="{Binding Name}" />
    <Button Content="Change name" Click="changeNameClick" />
</StackPanel>

コードビハインド:

public partial class Window1 : Window
{
    private SimpleObject so = new SimpleObject();

    public Window1()
    {
        InitializeComponent();

        this.so = new SimpleObject();
        so.Name = "Initial value";

        this.DataContext = so;

        var t = new DispatcherTimer(
            TimeSpan.FromSeconds(1), 
            DispatcherPriority.Normal,
            (s, e) => { this.so.Name = "Name changed at: " + DateTime.Now.ToString(); },
            Dispatcher);
    }

    private void changeNameClick(object sender, RoutedEventArgs e)
    {
        this.so.Name = "New value!!";
    }
}

public class SimpleObject
{
    private string mName = null;

    public string Name 
    {
        get { return mName; }
        set
        {
            if (mName != value)
            {
                mName = value;

                if (NameChanged != null)
                    NameChanged(this, EventArgs.Empty);
            }
        }
    }

    public event EventHandler NameChanged;
}
于 2012-12-01T18:50:12.917 に答える
3

あなたが言及するパターンは、WPFとWindowsフォーム(WinForms)に適用されます。

于 2012-12-01T15:36:39.107 に答える
-2

いいえ、WPFでは、DependencyPropertiesまたはを使用する必要がありますINotifyPropertyChanged。コレクションの場合INotifyCollectionChangedも、トリックを行います。

于 2012-12-01T15:27:55.087 に答える