简体   繁体   English

WPF MVVM处理数据网格单元更改

[英]WPF MVVM handle datagrid cell change

i try to catch CellEditEnding Event and get the row+column number and the new value to my view model. 我试图赶上CellEditEnding事件并获取行+列号和新值到我的视图模型。

i try this How do you handle data grid cell changes with MVVM? 我尝试使用MVVM如何处理数据网格单元更改? but i get this exception 但我得到这个例外

"the type 'GalaSoft_MvvmLight_Command' was not found.verify that you are not missing an assembly reference and that all reference assembly have been built". “找不到类型'GalaSoft_MvvmLight_Command'。请验证您没有缺少程序集引用,并且所有引用程序集均已构建”。 i have reference to GalaSoft.MvvmLight.WPF4.dll. 我已经引用了GalaSoft.MvvmLight.WPF4.dll。

this is my dataGrid: 这是我的dataGrid:

 <DataGrid MaxHeight="600" AutoGenerateColumns="False" VerticalScrollBarVisibility="Auto"
                  ItemsSource="{Binding BitTestParam,Mode=TwoWay}" GridLinesVisibility="None" RowBackground="{x:Null}" Background="{x:Null}"
                  BorderThickness="2" BorderBrush="Black" HeadersVisibility="Column" Foreground="Black" FontStyle="Italic" FontWeight="SemiBold">
            <i:Interaction.Triggers>
                <i:EventTrigger EventName="CellEditEnding">
                    <i:InvokeCommandAction Command="{Binding CellChangedCommand}" CommandParameter="{Binding}"/>
                    <!--<GalaSoft_MvvmLight_Command:EventToCommand PassEventArgsToCommand="True" Command="{Binding CellEditEndingCommand}"/>-->
                </i:EventTrigger>
            </i:Interaction.Triggers>
            <DataGrid.Columns>
                <DataGridTextColumn Header="Input Param" Binding="{Binding InputNames}"/>
                <DataGridTextColumn x:Name="InputValuesColumn" Header="Param value" Binding="{Binding InputValues}" />
                <DataGridTextColumn Header="Output Param" Binding="{Binding OutputNames}"/>
                <DataGridTextColumn Header="Measure value" Binding="{Binding OutputValues}"/>
                <DataGridTextColumn Header="Error Messages" Binding="{Binding ErrorMessages}"/>
                <DataGridTextColumn Header="Warning Messages" Binding="{Binding WarningMessages}" />
            </DataGrid.Columns>
        </DataGrid>

this is my relevant code in the viewModel: 这是我在viewModel中的相关代码:

public RelayCommand<object> CellChangedCommand
{
    get;
    set;
}

CellChangedCommand = new RelayCommand<object>(CellChangedEvent);

void CellChangedEvent(object obj)
{

}

i get my Command "CellChangedCommand" with parameter but i need to get the row+column number and the new value. 我得到带有参数的命令“ CellChangedCommand”,但我需要获取行+列号和新值。

Thanks 谢谢

I would make the user edit in a separate panel and handler validation there. 我将让用户在单独的面板中进行编辑,并在那里进行处理程序验证。 That's how this sample works: https://gallery.technet.microsoft.com/scriptcenter/WPF-Entity-Framework-MVVM-78cdc204 该示例就是这样工作的: https : //gallery.technet.microsoft.com/scriptcenter/WPF-Entity-Framework-MVVM-78cdc204

In that you will find some code which works out which binding just transferred data from the view to the viewmodel. 在那您将找到一些代码,这些代码可以算出哪个绑定只是将数据从视图传输到视图模型。 You could still use that even if the user edits in a datagrid. 即使用户在数据网格中进行编辑,您仍然可以使用它。 You'd just need a grid or panel around your datagrid. 您只需要在数据网格周围放置一个网格或面板即可。 It might even work in the datagrid, I'd have to try that to know for sure. 它甚至可以在数据网格中工作,我必须尝试确定一下。 But if you look in the project's resource dictionary you will see: 但是,如果您查看该项目的资源字典,将会看到:

    <Grid Visibility="{Binding IsInEditMode, Converter={StaticResource BooleanToVisibilityConverter}}" 
           Width="{Binding ElementName=dg, Path=ActualWidth}"
           Height="{Binding ElementName=dg, Path=ActualHeight}"
           >
                <i:Interaction.Triggers>
                    <local:RoutedEventTrigger RoutedEvent="{x:Static Validation.ErrorEvent}">
                        <e2c:EventToCommand
                                                Command="{Binding EditVM.TheEntity.ConversionErrorCommand, Mode=OneWay}"
                                                EventArgsConverter="{StaticResource BindingErrorEventArgsConverter}"
                                                PassEventArgsToCommand="True" />
                    </local:RoutedEventTrigger>
                    <local:RoutedEventTrigger RoutedEvent="{x:Static Binding.SourceUpdatedEvent}">
                        <e2c:EventToCommand
                                                Command="{Binding EditVM.TheEntity.SourceUpdatedCommand, Mode=OneWay}"
                                                EventArgsConverter="{StaticResource BindingSourcePropertyConverter}"
                                                PassEventArgsToCommand="True" />
                    </local:RoutedEventTrigger>
                </i:Interaction.Triggers>

Conversion failures or removing them are grabbed by the former and data transfer by the latter. 转换失败或删除失败由前者抓住,而数据传输则由后者抓住。

You need to mark bindings to notifyonsourceupdated - an example binding is: 您需要标记到notifyonsourceupdated的绑定-一个示例绑定是:

<TextBox Text="{Binding  EditVM.TheEntity.Address1, 
                        UpdateSourceTrigger=PropertyChanged, 
                        NotifyOnSourceUpdated=True,
                        NotifyOnValidationError=True,
                        Mode=TwoWay}"  />

Other code is in the sample if I miss something. 如果我错过了一些其他代码在示例中。 Routedeventtrigger 路由事件触发

public class RoutedEventTrigger : EventTriggerBase<DependencyObject>
{
    RoutedEvent routedEvent;
    public RoutedEvent RoutedEvent
    {
        get
        {
            return routedEvent;
        }
        set 
        { 
            routedEvent = value;
        }
    }

    public RoutedEventTrigger()
    {
    }
    protected override void OnAttached()
    {
        Behavior behavior = base.AssociatedObject as Behavior;
        FrameworkElement associatedElement = base.AssociatedObject as FrameworkElement;
        if (behavior != null)
        {
            associatedElement = ((IAttachedObject)behavior).AssociatedObject as FrameworkElement;
        } 
        if (associatedElement == null)
        {
            throw new ArgumentException("This only works with framework elements");
        }
        if (RoutedEvent != null)
        {
            associatedElement.AddHandler(RoutedEvent, new RoutedEventHandler(this.OnRoutedEvent));
        }
    }
    void OnRoutedEvent(object sender, RoutedEventArgs args)
    {
         base.OnEvent(args);
    }
    protected override string GetEventName()
    {
        return RoutedEvent.Name;
    }
}

Bindingsourcepropertyconverter 绑定源属性转换器

public class BindingSourcePropertyConverter: IEventArgsConverter
{
    public object Convert(object value, object parameter)
    {
        DataTransferEventArgs e = (DataTransferEventArgs)value;
        BindingExpression binding = ((FrameworkElement)e.TargetObject).GetBindingExpression(e.Property);
        return binding.ResolvedSourcePropertyName ?? "";
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM