wpf 未使用配备Caliburn Micro的MVVM更新数据网格中的编辑项目

bhmjp9jg  于 2023-01-02  发布在  其他
关注(0)|答案(2)|浏览(157)

我有一个GridViewModel,其中的DataGrid绑定到校准点的BindableCollection。该网格包含4列:No、Start、Stop和EstimatedCalibrationTime,用户可以直接在DataGrid中编辑值,编辑Start列的值时,EstimatedCalibrationTime列的值需要重新计算,编辑Stop列的值时,Start列的值需要重新计算,我面临两个问题,我真的不知道如何解决:
1.如何知道哪些栏目被编辑?
1.如何使用新的计算值更新数据网格?

public class CalibrationPoint
    {
        public int No { get; set; }
        public int Start { get; set; }
        public int Stop { get; set; }
        public double EstimatedCalibrationTime { get; set; }
    }

    public class GridViewModel : Screen
    {
        public BindableCollection<CalibrationPoint> CalibrationPoints { get; }

        private CalibrationPoint selectedCalibrationPoint;
        public CalibrationPoint SelectedCalibrationPoint
        {
            get => selectedCalibrationPoint;
            set
            {
                selectedCalibrationPoint = value;
                NotifyOfPropertyChange(() => SelectedCalibrationPoint);
            }
        }

        public GridViewModel()
        {
            CalibrationPoints = new BindableCollection<CalibrationPoint>();

            CalibrationPoints.Add(new CalibrationPoint() { No = 1, Start = 1, Stop = 2, EstimatedCalibrationTime = CalculateCalibrationTime(1, 2) });
            CalibrationPoints.Add(new CalibrationPoint() { No = 2, Start = 3, Stop = 5, EstimatedCalibrationTime = CalculateCalibrationTime(3, 5) });
            CalibrationPoints.Add(new CalibrationPoint() { No = 3, Start = 6, Stop = 8, EstimatedCalibrationTime = CalculateCalibrationTime(6, 8) });
        }

        private double CalculateCalibrationTime(int start, int stop)
        {
            var time = (start * 0.7) + (stop * 1.2);
            return time;
        }
    }
Window x:Class="Wpf_DataGridTest.Views.GridView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Wpf_DataGridTest.Views"
        mc:Ignorable="d"
        Title="GridView" Height="300" Width="400">
    <Grid>
        <DataGrid Grid.Column="1" 
                ItemsSource="{Binding CalibrationPoints, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" 
                AutoGenerateColumns="False"
                SelectedItem="{Binding Path=SelectedCalibrationPoint, Mode=TwoWay}"
                IsSynchronizedWithCurrentItem="True"
                CanUserAddRows="False"
                CanUserDeleteRows="False"
                CanUserReorderColumns="False"
                CanUserSortColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="no" Width="*" Binding="{Binding No}" IsReadOnly="True"/>
                <DataGridTextColumn Header="start" 
                                        Width="2*" 
                                        Binding="{Binding Start}">
                </DataGridTextColumn>
                <DataGridTextColumn Header="stop" 
                                        Width="2*" 
                                        Binding="{Binding Stop}"/>
                
                <DataGridTextColumn Header="estimated&#x0a;calibration&#x0a;time(s)" 
                                        Width="3*" 
                                        Binding="{Binding EstimatedCalibrationTime}"
                                        IsReadOnly="True"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>
4ktjp1zp

4ktjp1zp1#

当你在datagrid中编辑一个字段时,这个值会通过绑定到你的viewmodel属性的魔力转移过来,每行有一个CalibrationPoint viewmodel。
因此,编辑值将传输到匹配的CalibrationPoint示例。
该值将被设置在你的属性上。你有默认的空setter,但你不一定要这样做。
一种选择是在setter中调用逻辑。编写一个方法来执行计算。从setter中调用它。
就像这里所描述的:
https://social.technet.microsoft.com/wiki/contents/articles/30564.wpf-uneventful-mvvm.aspx#Change_of_Variable
这包括1)
从这里继续到2)你需要在你的视图模型上实现inotifypropertychanged,并且用任何字段的名字作为参数来引发属性changed,然后视图从视图模型中重新获得该属性的值。
这似乎是涵盖在这里:
https://doc.postsharp.net/inotifypropertychanged-caliburnmicro

ruoxqz4g

ruoxqz4g2#

我把CalibrationPoint模型 Package 成一个CalibrationPointViewModel,以便能够按照Andy的建议在setter中执行计算。现在DataGrid更新了,一切都正常了!不需要修改xaml。最终的viewmodel代码:

public class CalibrationPoint
{
    public int No { get; set; }
    public int Start { get; set; }
    public int Stop { get; set; }
    public double EstimatedCalibrationTime { get; set; }
}

public class CalibrationPointViewModel : PropertyChangedBase
{
    private CalibrationCalculator calibrationCalculator;

    public CalibrationPointViewModel()
    {
        calibrationCalculator = new CalibrationCalculator();
    }

    public int No { get; set; }

    private int start;

    public int Start
    {
        get { return start; }
        set 
        { 
            start = value;
            NotifyOfPropertyChange(() => Start);
            NotifyOfPropertyChange(() => EstimatedCalibrationTime);
        }
    }

    private int stop;

    public int Stop
    {
        get { return stop; }
        set 
        { 
            stop = value;
            Start = calibrationCalculator.CalculateStart(value);
            NotifyOfPropertyChange(() => Stop);
            NotifyOfPropertyChange(() => EstimatedCalibrationTime);
        }
    }

    private double estimatedCalibrationTime;

    public double EstimatedCalibrationTime
    {
        get 
        {
            estimatedCalibrationTime = calibrationCalculator.CalculateCalibrationTime(Start, Stop);
                return estimatedCalibrationTime; 
        }
        set 
        {
            estimatedCalibrationTime = value;
            NotifyOfPropertyChange(() => EstimatedCalibrationTime);
        }
    }
}

public class CalibrationCalculator
{
    public double CalculateCalibrationTime(int start, int stop)
    {
        var time = (start * 0.7) + (stop * 1.2);
        return time;
    }

    public int CalculateStart(int stop)
    {
        return stop - 1;
    }
}

public class GridViewModel : Screen
{
    public BindableCollection<CalibrationPointViewModel> CalibrationPoints { get; }

    private CalibrationPointViewModel selectedCalibrationPoint;
    public CalibrationPointViewModel SelectedCalibrationPoint
    {
        get => selectedCalibrationPoint;
        set
        {
            selectedCalibrationPoint = value;
            NotifyOfPropertyChange(() => SelectedCalibrationPoint);
        }
    }

    public GridViewModel()
    {
        CalibrationPoints = new BindableCollection<CalibrationPointViewModel>();
            
        CalibrationPoints.Add(new CalibrationPointViewModel() { No = 1, Start = 1, Stop = 2 });
        CalibrationPoints.Add(new CalibrationPointViewModel() { No = 2, Start = 3, Stop = 5 });
        CalibrationPoints.Add(new CalibrationPointViewModel() { No = 3, Start = 6, Stop = 8 });
    }
}

相关问题