0

I'm trying to cancel an edit when a bool returns as false. The bool is set to false once I've iterated through the selected cells and done some calculations. This is in the CellEditEnding function, but I'm using EventTrigger interactivity so it's all MVVM and I don't have the datagrid object to actually do a CancelEdit call when this bool is false.

Is there any way I can cancel an edit using MVVM? When I lose focus from the cell, it is still white...

This is how I've got round it at the moment... don't like it though...

In the code I do this... I just don't like doing this in the viewmodel... kinda breaks MVVM

    public void CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
    {
        bool isSuccess = true;

        if (e.EditAction == DataGridEditAction.Commit)
        {
            if (e.EditingElement is TextBox cellTextEdit && cellTextEdit.Text != string.Empty)
            {
                for (int iSelected = 0; iSelected < SelectedGridCellCollection.Count; ++iSelected)
                {
                     if (!isSuccess)
                     {
                         e.Cancel = true;

                          // Only "non" MVVM here, but if there is another way to do this then I'd
                         // be surprised...
                         DataGrid dg = sender as DataGrid;
                         dg.CancelEdit();
                      }
                 }
            }
       }
   }

In the XAML

                                <DataGrid Name="dataGrid" Width="550" ItemsSource="{Binding ObjSource}" 
                                          CanUserSortColumns="False" CanUserAddRows="false" 
                                          HorizontalAlignment="Stretch" 
                                          VerticalScrollBarVisibility="Auto"
                                          utils:DataGridSelectedCellsBehavior.SelectedCells="{Binding SelectedGridCellCollection, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                                          AutoGenerateColumns="False" 
                                          Background="{StaticResource ResourceKey=Polour}"
                                          SelectionUnit="Cell" 
                                          RowHeaderWidth="0" 
                                          RowStyle="{StaticResource DataGridRowStyle}" 
                                          AlternationCount="2" 
                                          FontFamily="{StaticResource ResourceKey=Light}" 
                                          CanUserResizeColumns="False" CanUserReorderColumns="False">
                                    <DataGrid.Resources>
                                        <Style BasedOn="{StaticResource {x:Type DataGridColumnHeader}}" TargetType="{x:Type DataGridColumnHeader}">
                                            <Setter Property="Background" Value="{StaticResource ResourceKey=Polour}"/>
                                            <Setter Property="Foreground" Value="White"/>
                                            <Setter Property="BorderBrush" Value="{StaticResource ResourceKey=Solour}"/>
                                            <Setter Property="BorderThickness" Value="0,0,0,1"/>
                                            <Setter Property="HorizontalAlignment" Value="Center"/>
                                            <Setter Property="VerticalAlignment" Value="Center"/>
                                            <Setter Property="HorizontalContentAlignment" Value="Center"/>
                                            <Setter Property="VerticalContentAlignment" Value="Center"/>
                                            <Setter Property="Margin" Value="5 0 5 0"/>
                                            <Setter Property="Height" Value="30"/>
                                            <Setter Property="Width" Value="Auto"/>
                                        </Style>
                                    </DataGrid.Resources>
                                    <DataGrid.Columns>
                                        <DataGridTextColumn Header="ll" Binding="{Binding Id}" IsReadOnly="True"></DataGridTextColumn>
                                    </DataGrid.Columns>
                                    <i:Interaction.Triggers>
                                        <i:EventTrigger EventName="CellEditEnding">
                                            <i:CallMethodAction TargetObject="{Binding}" MethodName="CellEditEnding"/>
                                        </i:EventTrigger>
                                    </i:Interaction.Triggers>
                                </DataGrid>
uaswpff
  • 75
  • 6
  • 2
    why the downvote :\ – uaswpff Sep 30 '19 at 14:41
  • If using `mvvm` pattern, you would have bindings etc. I am not seeing any? – Trevor Sep 30 '19 at 14:46
  • https://stackoverflow.com/questions/1048517/wpf-calling-commands-via-events but you would still break MVVM by having to reference the DataGrid class. – Felix Castor Sep 30 '19 at 14:46
  • I have bindings, but I have a ton of stuff connected to the DG in the bindings, and for the question I don't see them as necessary to post. – uaswpff Sep 30 '19 at 14:47
  • @FelixCastor yep if you see my edit that's what I've done. I don't like it... is there not any other way? Like, is there a way I can somehow send a trigger from that 'if' statement to CancelEdit? – uaswpff Sep 30 '19 at 14:47
  • `I'm trying to cancel an edit when a bool returns as false` from what exactly, if you have bindings, show your view model of these items in the grid, window etc. We need to be able to replicate your issue in order to help. – Trevor Sep 30 '19 at 14:48
  • I really don't see a problem putting this in code behind. As long as you aren't putting business logic in there. You are using the `DataGrid`'s method to cancel as well. – Felix Castor Sep 30 '19 at 14:48
  • @FelixCastor I see it as a breaking pattern, the OP logic depends on another property... If true/false cancel the edit; if bindings were in place it's easy to do in the VM... – Trevor Sep 30 '19 at 14:50
  • @Çöđěxěŕ It's just a boolean that does a `float.TryParse` on the cell you're trying to edit and if it is a string (text) and not a number, `isSuccess` will be false and it should cancel the edit. – uaswpff Sep 30 '19 at 14:51
  • @uaswpff my point is, it's not mvvm pattern. If this is for each cell, then this cell represents a property of some sorts in the VM. If it doesn't meet a condition another property would change.. – Trevor Sep 30 '19 at 14:52
  • Would the cancel method require a reference to the ViewModel? If not I don't see why it wouldn't still hold true to the MVVM pattern. – Felix Castor Sep 30 '19 at 14:54
  • guys I added some code.... let me know what you think... @FelixCastor the VM does have to be instantiated in order for this to occur because the `CellEditEnding` function is in the VM – uaswpff Sep 30 '19 at 14:57
  • Would it be possible to take it out of the VM and put it in code behind without having a reference to the ViewModel? – Felix Castor Sep 30 '19 at 14:58
  • Sadly no @FelixCastor, it iterates through a collection that is injected into the VM, so... it has to be in the VM. It's a matter of the that Cancel Edit call being the issue. Everything else is pure MVVM – uaswpff Sep 30 '19 at 15:01
  • @Çöđěxěŕ so you can see i have bindings. How do you suggest I do this then? – uaswpff Sep 30 '19 at 15:07
  • @uaswpff please see https://stackoverflow.com/questions/4897775/wpf-binding-ui-events-to-commands-in-viewmodel and specifically [this](https://stackoverflow.com/a/4897897/1797425) answer. – Trevor Sep 30 '19 at 15:10
  • @Çöđěxěŕ I think you misunderstand. I have done that in other places and with other things - this does not work for what I want. CellEditEnding is called this way, and if the boolean is false, CancelEdit must be called. How do you suggest to do this when the boolean is in the VM and is triggered at the end of CellEditEnding? – uaswpff Sep 30 '19 at 15:13
  • You need to create a command you bind to in the VM from the view. – Trevor Sep 30 '19 at 15:15
  • Fine but how would I fire that command from the VM since it is coming from the CellEditEnding function. Do you understand what I mean? – uaswpff Sep 30 '19 at 15:16
  • This is not something coming from the view persay. CellEditEnding is a command from the view yes. But this needs to trigger cancel, and that is done in the VM – uaswpff Sep 30 '19 at 15:17
  • `CellEditEnding is a command`, no, it's an event. You would need to create a command in the VM to bind to the `CellEditEnding` event in your xaml. – Trevor Sep 30 '19 at 15:18
  • Please see the XAML. This is *already* being done – uaswpff Sep 30 '19 at 15:19
  • Regardless if `CellEditEnding` is an event OR a command. How is CancelEdit going to be called. – uaswpff Sep 30 '19 at 15:20
  • `CancelEdit` needs to be called by CellEditEnding based on that boolean – uaswpff Sep 30 '19 at 15:20
  • `DataGrid` handling doesn't belong to the view model. When your view model references view objects and even subscribes to their events you should instantly know that you are on the wrong path. Also I doubt that what you are trying to achieve delivers good user experience. When I edit a cell I don't want to get interrupted and "kicked out" from edit. You should take a look at data validation especially with the `DataGrid`. This way the inputs/edits a user has done are validated and not committed until the user cancels the edit himself or corrects the errors (validation passes). – BionicCode Sep 30 '19 at 15:33
  • This is by far more user friendly. See Microsoft Docs: [How to: Implement Validation with the DataGrid Control](https://learn.microsoft.com/en-us/dotnet/framework/wpf/controls/how-to-implement-validation-with-the-datagrid-control). – BionicCode Sep 30 '19 at 15:34
  • Thanks @BionicCode - i'll take a look at changing the way editing works to make it better for the user - thanks for the input :). I did find an answer to my question - Attached Behaviour. This worked perfectly and allowed the datagrid to not been seen in the viewmodel, while I just attached a boolean that is set to true until a failure is made – uaswpff Sep 30 '19 at 15:41
  • https://www.codeproject.com/Questions/487418/WPFplusDataGridplusProblempluswhenplushiddenplusan – uaswpff Sep 30 '19 at 15:41
  • I know that what you are trying to do is possible. I just want you to consider to take the standard concept of letting the user decide what to do. Imaging you are filling a form and every time you enter a disallowed character your editing gets cancelled and maybe even your input gets discarded. You the have to grab your mouse again, click in to the input field and enter input until the next time you get kicked. I am pretty sure this will get you annoyed after the very first time this happens. If this is an application you need to work with daily you'd uninstall it and find something better. – BionicCode Sep 30 '19 at 15:49
  • Fair point BionicCode... Totally agree with you now, thanks :-). I'm sad I got so many downvotes... didn't think the question was formulated badly :\ – uaswpff Sep 30 '19 at 15:50
  • It wasn't me. But gave you an upvote to compensate. You improved your question by adding some code. – BionicCode Sep 30 '19 at 15:51
  • Thanks man :) - I don't know how many times I've got to 100 rep and then for some reason because of a question I've posted I then have my account suspended because I get a -1.... appreciate it though, hopefully this'll keep my account alive for another day... I'll implement that editing process you spoke about though... – uaswpff Sep 30 '19 at 15:53
  • 1
    I agree, This down voting is not a good feature the way it is implemented. People use it too often. Worst they don't provide an explanation that helps to improve. That's not critic. If there would be suggestions on how to improve the question, it would be more ok. So you have to ignore it. But I can feel how this is causing frustration. – BionicCode Sep 30 '19 at 16:04
  • 1
    Just try to always post compiling code and explanations (or code comments) that helps to reproduce your problems. This should keep you away from most of the down votes. If you need help try to help to give you a good answer without wasting once time. This can be annoying sometimes. – BionicCode Sep 30 '19 at 16:07
  • Thanks BionicCode for your detailed advice - I appreciate it :). I'll definitely keep bearing that in mind... – uaswpff Sep 30 '19 at 16:58
  • Comments are not for extended discussion; this conversation has been [moved to chat](https://chat.stackoverflow.com/rooms/200213/discussion-on-question-by-uaswpff-canceledit-on-datagrid-mvvm). – Samuel Liew Oct 01 '19 at 07:04

1 Answers1

0

https://www.codeproject.com/Questions/487418/WPFplusDataGridplusProblempluswhenplushiddenplusan

Solution 2 solved my problem if anyone is looking at editing Datagrids in this way - though BionicCode's suggestion is a much better one for user experience

uaswpff
  • 75
  • 6