C# 当某些其他更改时,DataGrid中的依赖列不会更改(WPF C)

C# 当某些其他更改时,DataGrid中的依赖列不会更改(WPF C),c#,.net,wpf,data-binding,datagrid,C#,.net,Wpf,Data Binding,Datagrid,我在我的应用程序中有一堆订单,我想在datagrid中显示它们,并在原地编辑它们的属性。有一个名为Order的类,其权重属性取决于Item.weight和Order.Count。在ObservableCollection订单绑定到的datagrid中,我希望就地更改行。城市和项目值正在更改,但当项目或计数更改时,UI中的权重不会更新 -MyViewModel public class Order : INotifyPropertyChanged { private int _OrderI

我在我的应用程序中有一堆订单,我想在datagrid中显示它们,并在原地编辑它们的属性。有一个名为Order的类,其权重属性取决于Item.weight和Order.Count。在ObservableCollection订单绑定到的datagrid中,我希望就地更改行。城市和项目值正在更改,但当项目或计数更改时,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>

例如:当我在datagrid中编辑一行时,我想更新整个属性,但在这种情况下,我可以更改订单的项目、计数和城市,但权重不会更新。

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

将绑定设为单向,因为该值将始终在源中重新计算

<DataGridTextColumn Binding="{Binding Weight, Mode=OneWay}"
                    Header="وزن"
                    Width="100"
                    IsReadOnly="True"/>
通知计算的源属性中的相关更改。如果Item.Weight可能在Item实例中发生更改,则需要额外处理

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));
    }
}
删除访问权重设置器的所有内容,例如在构造函数中

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

<Window
    ... your default generated window class, nothing special ... >
    <Grid x:Name="grid1">
        <DataGrid ItemsSource="{Binding}"/>
    </Grid>
</Window>
主窗口构造函数:

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键或该行失去焦点。更新源后,相关计算列的值将更改为数值的2倍。

欢迎使用SO!第一个问题做得好。你可以试着弄清楚你有什么问题。也许可以尝试重复您发布的代码数量,因为很难提取问题所在。另外,请详细说明根据您的情况,在代码中应在何处进行字段切换,并举例说明您希望获取的内容以及现在正在发生的事情。非常感谢。我对我的问题做了一些更改。如果我理解正确,显示的重量将是从Count*Item计算出来的值。重量,用户永远不会直接修改重量值?我现在假设一下,然后写一个答案……谢谢你的回答。我按照你说的步骤做了,但没有起作用。我想因为我是MVVM新手,所以我无法理解。我找到了一种解决方法,在项目或计数发生变化时分配权重:set{{u item=value;\u Weight=\u count*\u item.Weight;raiseProperteChanged;}set{\u Count=value;\u Weight=\u Count*\u Item.Weight;raisepropertechanged;}@Eti我添加了一个小示例,也许您会发现了解计算列很有用,并且它可能会帮助您理解为什么在您的案例中它不起作用。
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));
    }
}
public MainWindow()
{
    InitializeComponent();

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

    grid1.DataContext = data;
}