简体   繁体   中英

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.

i try this How do you handle data grid cell changes with 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". i have reference to GalaSoft.MvvmLight.WPF4.dll.

this is my 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:

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.

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

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:

<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 ?? "";
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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