Open heckl opened 4 months ago
Local copy of the repro: ImmediateValidationBindingTest.zip Also it is helpful to include the actual error text, which is
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=FinalizeNameCommand; DataItem=null; target element is 'TextBoxLostFocusBehavior' (HashCode=26534308); target property is 'LostFocusCommand' (type 'ICommand')
It is not entirely clear to me what you are trying to achieve, but a temp property sounds like an extreme measure. So you are trying to update the DB before the row or even cell is committed, even if it has validation errors? Can you not use CellEditEnding event?
As far as the error goes, it also seems correct, it happens when the element is created but not added to the tree yet, and at that point it is also true that DataContext is null.
What "other problems in the code later" this causes?
Dear @miloush I want immediate validiton, so when I press '/' an error should be displayed at once. But I only want to refresh the db when I finished editing the cell (when I leave the cell).
<DataGridTextColumn.EditingElementStyle>
<Style TargetType="{x:Type TextBox}">
<Setter Property="local:BehaviorInStyleAttacher.Behaviors">
<Setter.Value>
<collections:ArrayList>
<local:TextBoxLostFocusBehavior LostFocusCommand="{Binding FinalizeNameCommand}" />
</collections:ArrayList>
</Setter.Value>
</Setter>
</Style>
</DataGridTextColumn.EditingElementStyle>
I do not understand while a binding error is indicated when the binding actually works.
That is what the CellEditEnding is for, it will get called when the cell is about to finish editing, and you get an opportunity to either cancel and stay in editing mode, or, in your case, save to the db.
I do not understand while a binding error is indicated when the binding actually works.
I will blame the XAML Binding Failures tool window for this. You need to understand that this is not a state of the app. This is binding events collected throughout the debugging session. The binding error happens during XAML loading when the element is created and styled and before it is added to the visual tree where it gets the DataContext. Once you add it to the tree, there isn't any error, but the tool window does not know that. It just keeps adding new entries as errors are logged every time the databinding is evaluated. There is no "you remember that error I told you before? It's gone" event. I prefer checking for databinding errors in the Output window because it reflects the "this happened at this point in time" reality.
Dear @miloush
Thank you for the explanation. I understand that the error was temporary and it is not cleared automatically.
I created and updated version.
CellEditEnding event would work fine. Previously I used the LostFocus event and there was no problem with it. But I try to avoid using event and code behind. In the updated version you can see this:
<local:DataGridTextColumnEx Width="300"
Binding="{Binding TempName, TargetNullValue='', ValidatesOnDataErrors=True, UpdateSourceTrigger=PropertyChanged}"
FinalizeCommand="{Binding FinalizeNameCommand}"
Header="Name">
<DataGridTextColumn.EditingElementStyle>
<Style TargetType="{x:Type TextBox}">
<Setter Property="local:BehaviorInStyleAttacher.Behaviors">
<Setter.Value>
<collections:ArrayList>
<local:TextBoxLostFocusBehavior LostFocusCommand="{Binding FinalizeCommand, RelativeSource={RelativeSource AncestorType={x:Type local:DataGridTextColumnEx}}}" />
</collections:ArrayList>
</Setter.Value>
</Setter>
</Style>
</DataGridTextColumn.EditingElementStyle>
</local:DataGridTextColumnEx>
DataGridTextColumnEx
only contains an additional dependency property, the FinalizeCommand
. I introduced and additional level on indirection (LostFocusCommand refers to the FinalizeCommand, and it refers to the FinalizeNameCommand), so that I can use the same style at other similar columns. Now binding error is indicated at both command, and now the binding does not work. Can you tell me why?
Description
I wanted to have data validation at once in WPF. At the same time I wanted to detect LostFocus, this is the time I modify the DB. Moreover, I needed this in a
DataGrid
. I introduced a temp property. I use thePropertyChanged
at theTempName
so the validation happens at once and used the event handler atLostFocus
. The event handler copied theTempName
to theName
and triggered the DB change. This method worked.I wanted to use Behavior instead of event handler.
FinalizeNameCommand
copies theTempName
to theName
. Visual Studio says there is a Binding problem atFinalizeNameCommand
though the binding works.The binding error says the
DataContext
is null, it should be the object behind the selected row,Person
.FinalizeNameCommand
is in that object and it is executed as expected. It seems the Binding is evaulated before theDataContext
is set, that is why an error is shown. Later theDataContext
is set and the binding is reevaulated (?), that is whyFinalizeNameCommand
works.The problem is not only a wrong error message. This causes other problems in the code later.
Reproduction Steps
https://www.dropbox.com/scl/fi/pugbf1mxo72yjv64sqt8x/ImmediateValidationBindingTest.zip?rlkey=cflx26ayz6kusz3vino1mf90l&dl=0
Download the solution. Run the program See the binding error Modify a name and see that
FinalizeNameCommand
is executedExpected behavior
There should be no binding error
Actual behavior
There is binding error
Regression?
No response
Known Workarounds
use events instead of behavior
Impact
No response
Configuration
.net8 windows x64
Other information
No response