【问题标题】:Dependent Column in DataGrid not change when some other changes ( WPF C#)当其他一些更改时,DataGrid 中的依赖列不会更改(WPF C#)
【发布时间】:2018-07-11 20:52:28
【问题描述】:

我的应用程序中有一堆Orders,我想在数据网格中显示它们并就地编辑它们的属性。有一个名为Order 的类,其权重属性取决于Item.WeightOrder.Count。在ObservableCollection<Order> Orders 绑定的数据网格中,我想就地更改行。 CityItem 值正在更改,但 WeightItemCount 更改时不会在 UI 中更新。

--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>

例如:当我在数据网格中编辑一行时,我想更新整个属性,但在这种情况下,我可以更改 OrderItemCountCity,但权重不会更新。

【问题讨论】:

  • 欢迎来到 SO!你的第一个问题做得很好。您可以尝试更清楚地说明您遇到的问题。也许尝试减少您发布的代码量,因为很难提炼出问题所在。另外,请详细说明在代码中应该根据您的情况切换字段的位置,举例说明您想要实现的目标以及现在发生的情况。
  • 非常感谢。我对我的问题进行了一些更改。
  • 如果我理解正确,显示的Weight 将是Count * Item.Weight 的计算值,用户永远不会直接修改Weight 值?我现在假设它并为它写一个答案......

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


【解决方案1】:

由于您想显示基于其他属性计算得出的Weight 值,您应该更改代码的以下部分:

单向绑定,因为值总是会在源代码中重新计算。

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

将属性写为 get-only 计算。

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 itemtype定义:

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 倍。

【讨论】:

  • 感谢您的回答。我已经按照你说的步骤做了,但是没有用。我想因为我是 MVVM 的新手,所以我无法弄清楚。我找到了解决它的方法,每当项目或计数发生变化时分配权重:set{ _Item = value; _Weight = _Count * _Item.Weight; RaiseProperChanged(); } set { _Count = value; _Weight = _Count * _Item.Weight; RaiseProperChanged(); }
  • @Eti 我添加了一个小例子,也许你会发现了解计算列很有用,它可以帮助你理解为什么它在你的情况下不起作用。
猜你喜欢
  • 2018-04-15
  • 1970-01-01
  • 2012-06-22
  • 1970-01-01
  • 2011-08-05
  • 1970-01-01
  • 2017-08-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多