WPF 中带有 INotifyPropertyChanged 的​​绑定列表

BindingList with INotifyPropertyChanged in WPF

要让 UI 得到通知,属性 "差异 的正确方法是什么? " 在以下代码示例中发生了变化?

属性 是只读的。 属性 的值必须始终根据其他属性计算。

MainWindow.xaml:

<Window x:Name="winCalcs" x:Class="BindingList.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:m="clr-namespace:BindingList"
        Title="Calculations" Height="350" Width="525">
    <Window.Resources>
        <m:OperationList x:Key="OperationData"/>
        <CollectionViewSource x:Key="Operations" 
                              Source="{StaticResource ResourceKey=OperationData}"/>
    </Window.Resources>

    <Grid>
        <TabControl x:Name="tabsMain">
            <TabItem x:Name="tab01" Header="Tab 1">
                <DataGrid x:Name="dg01"
                          ItemsSource="{Binding 
                    Source={StaticResource ResourceKey=Operations}, 
                    UpdateSourceTrigger=PropertyChanged}" />
            </TabItem>
            <TabItem x:Name="tab02" Header="Tab 2">
                <DataGrid x:Name="dg02" 
                          ItemsSource="{Binding 
                    Source={StaticResource ResourceKey=Operations}, 
                    UpdateSourceTrigger=PropertyChanged}" />
            </TabItem>
        </TabControl>
    </Grid>

</Window>

Operation.cs:

namespace BindingList
{
    class Operation : INotifyPropertyChanged 
    {
        private float _minuend;

        private float _subtrahend;

        public float Minuend
        {
            get
            {
                return this._minuend;
            }
            set
            {
                if (this._minuend == value) return;
                this._minuend = value;
                this.NotifyPropertyChanged("Minuend");
            }
        }

        public float Subtrahend
        {
            get
            {
                return this._subtrahend;
            }
            set
            {
                if (this._subtrahend == value) return;
                this._subtrahend = value;
                this.NotifyPropertyChanged("Subtrahend");
            }
        }

        public float Difference 
        {
            get
            {
                return Minuend - Subtrahend;
            }
            private set {}
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(string p)
        {
            if (PropertyChanged != null) 
                PropertyChanged(this, new PropertyChangedEventArgs(p));
        }
    }
}

OperationList.cs:

namespace BindingList
{
    class OperationList : BindingList<Operation>
    {
        public OperationList()
        {
            Add(new Operation());
        }
    }
}
MinuendSubtrahend 改变时,

Difference 改变。这意味着您需要在 MinuendSubtrahend 的集合中通知 Difference 的变化。

差异不需要属性setter。

附带说明一下,没有必要在任何地方都使用 this

public float Minuend
{
    get
    {
        return _minuend;
    }
    set
    {
        if (_minuend == value) return;
        _minuend = value;
        NotifyPropertyChanged("Minuend");
        NotifyPropertyChanged("Difference");
    }
}

public float Subtrahend
{
    get
    {
        return _subtrahend;
    }
    set
    {
        if (_subtrahend == value) return;
        _subtrahend = value;
        NotifyPropertyChanged("Subtrahend");
        NotifyPropertyChanged("Difference");
    }
}

public float Difference 
{
    get
    {
        return Minuend - Subtrahend;
    }
}

在这些情况下,我通常会显式设置 属性 并引发 PropertyChanged 事件。

namespace BindingList
{
    class Operation : INotifyPropertyChanged
    {
        private float _minuend;
        private float _subtrahend;
        private float _difference;
        public float Minuend
        {
            get
            {
                return this._minuend;
            }

            set
            {
                if (this._minuend == value)
                    return;
                this._minuend = value;
                this.NotifyPropertyChanged("Minuend");
                this.UpdateDifference();
            }
        }

        public float Subtrahend
        {
            get
            {
                return this._subtrahend;
            }

            set
            {
                if (this._subtrahend == value)
                    return;
                this._subtrahend = value;
                this.NotifyPropertyChanged("Subtrahend");
                this.UpdateDifference();
            }
        }

        private void UpdateDifference()
        {
            this.Difference = this.Minuend - this.Subtrahend;
        }

        public float Difference
        {
            get
            {
                return this._difference
            }

            private set
            {
                if (this._difference == value)
                    return;
                this._difference = value;
                this.NotifyPropertyChanged("Difference");
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged(string p)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(p));
        }
    }
}