当其他一些更改时,DataGrid中的从属列不会更改(WPF C#)

时间:2018-02-01 13:47:47

标签: c# .net wpf data-binding datagrid

我的应用程序中有一堆Order,我希望在datagrid中显示并在其中编辑它们的属性。有一个名为Order的类,其权重属性取决于Item.WeightOrder.Count。在ObservableCollection<Order> Orders绑定到的数据网格中,我想要更改行。 CityItem值正在变化,但WeightItem更改时,Count在用户界面中不会更新。

- MyViewModel

public class Order : INotifyPropertyChanged
{
    private int _OrderId;

    public int OrderId
    {
        get { return _OrderId; }
        set
        {
            _OrderId = value;
            RaiseProperChanged();
        }
    }
    private City _City;
    public City City
    {
        get { return _City; }
        set
        {
            _City = value;
            RaiseProperChanged();
        }
    }
    private Item _Item;
    public Item Item
    {
        get { return _Item; }
        set
        {
            _Item = value;
            RaiseProperChanged();
        }
    }
    private int _Count;
    public int Count
    {
        get { return _Count; }
        set
        {
            _Count = value;
            RaiseProperChanged();
        }
    }
    private int _Weight;
    public int Weight
    {
        get { return _Weight; }
        set
        {
            _Weight = value;
            RaiseProperChanged();
        }
    }
    public static ObservableCollection<Order> GetOrders()
    {
        var Orders = new ObservableCollection<Order>();
        return Orders;
    }
    public DateTime DateOfOrder { set; get; }
    public Order()
    {

    }
    public Order(int _id, City _cty, Item _itm, int _count)
    {
        OrderId = _id;
        _City = _cty;
        _Item = _itm;
        Count = _count;
        Weight = _itm.Weight * _count;
        DateOfOrder = DateTime.Now;
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void RaiseProperChanged([CallerMemberName] string caller = "")
    {

        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(caller));
        }
    }
}

}

- 我的观点

<DataGrid x:Name="Orders"
              FlowDirection="RightToLeft"
              Margin="20,0,20,0"
              AutoGenerateColumns="False"
              DataGridCell.Selected="DataGrid_GotFocus"
              CanUserAddRows="True"
              SelectionUnit="FullRow"
              Height="250">
        <DataGrid.Columns>
            <DataGridTextColumn Binding="{Binding OrderId, 
                    Mode=TwoWay, 
                    UpdateSourceTrigger=PropertyChanged}"
                                Header="ردیف"
                                FontFamily="{StaticResource BLotus}"
                                Width="70"
                                IsReadOnly="True"/>

            <DataGridComboBoxColumn SelectedItemBinding="{Binding City, 
                    Mode=TwoWay, 
                    UpdateSourceTrigger=PropertyChanged}"
                                    DisplayMemberPath="Name"
                                    x:Name="citytoadd"
                                    Header="شهر"
                                    Width="150"
                                    />
            <DataGridComboBoxColumn Header="محصول"
                                    x:Name="itemtoadd"
                                    SelectedItemBinding="{Binding Item, 
                    Mode=TwoWay, 
                    UpdateSourceTrigger=PropertyChanged}"
                                    DisplayMemberPath="Name"
                                    Width="350" />
            <DataGridTextColumn Binding="{Binding Count, 
                    Mode=TwoWay, 
                    UpdateSourceTrigger=PropertyChanged}"
                                Header="تعداد"
                                Width="75"
                                />
            <DataGridTextColumn Binding="{Binding Weight, 
                    Mode=TwoWay, 
                    UpdateSourceTrigger=PropertyChanged}"
                                Header="وزن"
                                Width="100"
                                IsReadOnly="True"/>
        </DataGrid.Columns>
    </DataGrid>

例如:当我在datagrid中编辑一行时,我想更新整个属性,但在这种情况下,我可以更改{{1}的ItemCountCity但是重量不会更新。

1 个答案:

答案 0 :(得分:1)

由于您希望根据其他属性显示计算出的Weight值,因此您应该更改代码的以下部分:

单向进行绑定,因为值将始终在源中重新计算。

<DataGridTextColumn Binding="{Binding Weight, Mode=OneWay}"
                    Header="وزن"
                    Width="100"
                    IsReadOnly="True"/>

将该属性写为只进行计算。

public int Weight
{
    get { return Item.Weight * Count; } // TODO: adjust if Item can be null
}

通知计算源属性的相关更改。如果Item.Weight可能在项目实例中发生变化,则需要进行额外处理。

private Item _Item;
public Item Item
{
    get { return _Item; }
    set
    {
        _Item = value;
        RaiseProperChanged();
        RaiseProperChanged(nameof(Weight));
    }
}
private int _Count;
public int Count
{
    get { return _Count; }
    set
    {
        _Count = value;
        RaiseProperChanged();
        RaiseProperChanged(nameof(Weight));
    }
}

删除访问Weight setter的所有内容(例如在构造函数中)。

有关计算属性,请参阅以下最小工作示例。在这种情况下,我依赖于自动生成的列,但手写列也应该可以。

<Window
    ... your default generated window class, nothing special ... >
    <Grid x:Name="grid1">
        <DataGrid ItemsSource="{Binding}"/>
    </Grid>
</Window>

具有依赖属性Calculated的Viewmodel项类型定义:

public class ExampleItemViewModel : INotifyPropertyChanged
{
    private int _Number;
    public int Number
    {
        get { return _Number; }
        set
        {
            _Number = value;
            NotifyPropertyChanged();
            NotifyPropertyChanged("Calculated");
        }
    }

    public int Calculated { get { return 2 * Number; } }


    // INotifyPropertyChanged implementation
    public event PropertyChangedEventHandler PropertyChanged;
    protected void NotifyPropertyChanged([CallerMemberName] string prop = null)
    {
        var handler = PropertyChanged;
        if (handler != null) handler(this, new PropertyChangedEventArgs(prop));
    }
}

MainWindow构造函数:

public MainWindow()
{
    InitializeComponent();

    var data = new List<ExampleItemViewModel>();
    data.Add(new ExampleItemViewModel { Number = 1 });
    data.Add(new ExampleItemViewModel { Number = 2 });

    grid1.DataContext = data;
}

应该发生什么:DataGrid自动生成Number的可编辑列和Calculated的只读列。由于列是自动生成的,因此默认行为适用:更改数字时,源不会立即更新,因为行处于编辑模式。它将在编辑完成后更新(例如,您按Enter键或该行失去焦点)。更新源后,相关Calculated列值将更改为Number值的2倍。