每次击键时都会调用转换器,而不是在用户输入结束时调用
自从切换到 .NET 4.0 以来,我在数据输入方面遇到了问题。 在我的 Xceed 3.7 网格中,用户过去能够在单元格中键入一个值,当他们单击或按 Enter 时,将调用绑定转换器的 ConvertBack
方法,解析用户输入值并以所需的格式存储。
现在突然之间,这种情况发生在每次击键上 - 这会导致一个巨大的问题,因为如果用户删除一个数字并开始输入另一个数字(比如说 -100),一旦他们输入负号,convertback 会触发并抛出异常,因为“-”不是可解析的字符串,并且该值将被恢复。
我认为问题很清楚,所以现在我将粘贴一些代码。
用户输入的列如下所示:
<xcdg:DataGridControl x:Name="AggCatGrid01"
ItemsSource="{Binding Source={StaticResource myDataSource}}" >
<xcdg:DataGridControl.Columns>
...
<xcdg:Column VisiblePosition="0" FieldName="SomeValue" Title="Some Value"
CellEditor="{StaticResource PercentageEditor}"
CellContentTemplate="{StaticResource EditablePercent2CellContentTemplate}" />
数据网格都共享相同的样式:
<Style x:Key="{x:Type xcdg:DataGridControl}" TargetType="{x:Type xcdg:DataGridControl}">
<Setter Property="UpdateSourceTrigger" Value="CellEndingEdit"/>
<Setter Property="AutoCreateColumns" Value="False"/>
<Setter Property="EditTriggers" Value="BeginEditCommand, CellIsCurrent, ActivationGesture"/>
<Setter Property="CellEditorDisplayConditions" Value="CellIsCurrent"/>
<Setter Property="NavigationBehavior" Value="CellOnly"/>
请注意,UpdateSourceTrigger
设置为 CellEndingEdit
。我本以为这将负责何时调用转换器并更新绑定值。不管怎样,只要切换 .NET4 就可以改变控件。
这是您在上面看到的列的数据模板:
<!-- Styles used when editable cells are being edited. -->
<xcdg:CellEditor x:Key="PercentageEditor">
<xcdg:CellEditor.EditTemplate>
<DataTemplate>
<xcdg:AutoSelectTextBox Style="{StaticResource DefaultAutoSelectTextBox}"
Text="{xcdg:CellEditorBinding Converter={StaticResource EditablePercentageConverter}}" />
</DataTemplate>
</xcdg:CellEditor.EditTemplate>
</xcdg:CellEditor>
我认为转换器代码本身是无关紧要的,因此除非有要求,否则我将忽略它。问题是每次击键都会调用它。
如果你能阐明这一点,我会欣喜若狂。我的意思是,如果没有解决方案,我可能必须回滚所有 .NET 4.0 增强功能,或者将下一个版本推迟一个月以上,重写所有数据网格以不再使用 xceed。谢谢你们。
更新 #1
我实际上想出了一个相当聪明的解决方法(以我的谦虚观点),其中我引入了一个虚拟文本块来保存 CellEditorBinding xceed 强制我们在数据模板中使用。然后,我将输入控件更改为绑定到文本块的文本属性,而不是直接绑定到 CellEditorBinding,这允许我指定自己的绑定模式。在这里,我能够将模式设置为“lostFocus”,主要问题得到解决!不再在每次击键时调用转换器,而是仅在用户离开单元格或按 Enter 时调用。
<xcdg:CellEditor x:Key="PercentageEditor">
<xcdg:CellEditor.EditTemplate>
<DataTemplate>
<Grid>
<TextBlock x:Name="bind_source" Text="{xcdg:CellEditorBinding}" Visibility="Collapsed"/>
<xcdg:AutoSelectTextBox Style="{StaticResource DefaultAutoSelectTextBox}"
Text="{Binding ElementName=bind_source, Path=Text, Mode=TwoWay, UpdateSourceTrigger=LostFocus, Converter={StaticResource EditablePercentageConverter}}" />
</Grid>
</DataTemplate>
</xcdg:CellEditor.EditTemplate>
</xcdg:CellEditor>
但正如您可以想象的那样,这一间接层导致了一些其他小问题,例如破坏验证。奇怪的是,现在当用户输入无效数据时,转换器会抛出一个异常,xceed 会捕获该异常并使用该异常来打开单元格的错误模板,但更正错误并按 Enter 键不再起作用。用户唯一的选择是按 ESC 键,导致单元格值恢复并失去焦点,然后才能更正其输入。
我仍然希望有一个更优雅的解决方案来解决这个问题。
更新 #2
我在 Xceed 支持论坛上发现一位开发人员在这篇文章中提出了与我相同的问题:http://silverlightdatagrid.com/CS/forums/permalink/31548/31516/ShowThread.aspx#31516。
许多用户似乎对您的示例感到完全困惑(这些示例对于 .Net 4.0 来说基本上已经过时),并且仅使用 xcdg:CellEditorBinding 来定位您自己的控件,该控件似乎仅支持 PropertyChanged 验证。< /p>
不幸的是,没有提供任何解决方案。他确实提出了一种更优雅地更改更新源触发器的策略,我可以采用该策略,但我仍然遇到验证错误冻结单元格的问题,直到用户点击 ESC。
<xcdg:AutoSelectTextBox Style="{StaticResource DefaultAutoSelectTextBox}"
Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=xcdg:DataCell},
Path=Content, UpdateSourceTrigger=LostFocus,
Converter={StaticResource EditablePercentageConverter}}" />
更新 #3
我已经确认,通过更新到 Xceed DataGrid 版本 4.3(试用版),问题自行消失,因为在该版本中,Xceed 更新了其 xcdg :CellEditorBinding
UpdateSourceTrigger
与 .Net4.0 不兼容。然而,因为 Xceed 的许可证只包含 6 个月的错误修复更新,然后您就必须支付全新的许可证费用(荒谬),而且我没有看到任何公司授权 1200 美元的单曲费用开发人员许可费使用最新的 Xceed dll 只是为了解决这个小错误,我仍然会努力在 3.7 版本的 Xceed 中找到完整的解决方法。我将为有能力烧钱的开发人员介绍这个“解决方案”。
事实证明,升级到 4.3 并没有解决问题。这似乎只是因为我忘记取消之前的更改。即使在最新版本中,Xceed 仍然没有在 CellEditorBinding
上公开 UpdateSourceTrigger
属性。
I'm having a problem with data entry since switching to .NET 4.0.
In my Xceed 3.7 grid, the user used to be able to type a value into a cell, and when they clicked away or hit enter, the bound converter's ConvertBack
method would be called, parsing the user input value and storing in the desired format.
Now all of the sudden, this is happening every keystroke - which is causing a huge problem, because if the user erases a number and starts typing another one, (lets say -100), as soon as they type the negative sign, the convertback fires and throws an exception because "-" is not a parsable string, and the value is reverted.
I think the problem is pretty clear, so now I'll paste in some code.
Columns for user input appear as follows:
<xcdg:DataGridControl x:Name="AggCatGrid01"
ItemsSource="{Binding Source={StaticResource myDataSource}}" >
<xcdg:DataGridControl.Columns>
...
<xcdg:Column VisiblePosition="0" FieldName="SomeValue" Title="Some Value"
CellEditor="{StaticResource PercentageEditor}"
CellContentTemplate="{StaticResource EditablePercent2CellContentTemplate}" />
Datagrids all share the same style:
<Style x:Key="{x:Type xcdg:DataGridControl}" TargetType="{x:Type xcdg:DataGridControl}">
<Setter Property="UpdateSourceTrigger" Value="CellEndingEdit"/>
<Setter Property="AutoCreateColumns" Value="False"/>
<Setter Property="EditTriggers" Value="BeginEditCommand, CellIsCurrent, ActivationGesture"/>
<Setter Property="CellEditorDisplayConditions" Value="CellIsCurrent"/>
<Setter Property="NavigationBehavior" Value="CellOnly"/>
Notice that UpdateSourceTrigger
is set to CellEndingEdit
. I would have thought that this right here would be responsible for when the converters get called and the bound value is updated. Whatever controls that changed just by switching .NET4 though.
Here's the data template for the column you saw used above:
<!-- Styles used when editable cells are being edited. -->
<xcdg:CellEditor x:Key="PercentageEditor">
<xcdg:CellEditor.EditTemplate>
<DataTemplate>
<xcdg:AutoSelectTextBox Style="{StaticResource DefaultAutoSelectTextBox}"
Text="{xcdg:CellEditorBinding Converter={StaticResource EditablePercentageConverter}}" />
</DataTemplate>
</xcdg:CellEditor.EditTemplate>
</xcdg:CellEditor>
I think the converter code itself is irrelevant, so I'll leave it out unless it's requested. The problem is that it's getting called every keystroke.
If you can shed any light on this, I'd be ecstatic. I mean, I might have to roll back all my .NET 4.0 enhancements, or delay my next release by upwards of a month rewriting all my datagrids to no longer use xceed if there isn't a solution to this. Thanks guys.
Update #1
I actually came up with a moderately clever workaround (in my modest opinion) where I introduce a dummy textblock to hold the CellEditorBinding xceed forces us to use in the datatemplate. I then changed my input control to bind to the textblock's text property rather than the CellEditorBinding directly, which allowed me to specify my own binding mode. Here I was able to set the mode to 'lostFocus' and the major problem was solved! Converter is no longer being called on every keystroke, but only when the user leaves the cell or hits enter.
<xcdg:CellEditor x:Key="PercentageEditor">
<xcdg:CellEditor.EditTemplate>
<DataTemplate>
<Grid>
<TextBlock x:Name="bind_source" Text="{xcdg:CellEditorBinding}" Visibility="Collapsed"/>
<xcdg:AutoSelectTextBox Style="{StaticResource DefaultAutoSelectTextBox}"
Text="{Binding ElementName=bind_source, Path=Text, Mode=TwoWay, UpdateSourceTrigger=LostFocus, Converter={StaticResource EditablePercentageConverter}}" />
</Grid>
</DataTemplate>
</xcdg:CellEditor.EditTemplate>
</xcdg:CellEditor>
As you can imagine though, this layer of indirection has cause a few other minor issues, such as breaking validation. Oddly enough, now when the user types invalid data, the converter throws an exception which xceed catches and uses to turn on the cell's error template, but correcting the error and hitting enter no longer works. The user's only option is to hit the ESC key, causing the cell value to revert and lose focus, before they can correct their entry.
I'm still hoping for a more elegant solution that will fix this.
Update #2
I found a developer on Xceed support forums which presented the same issue as me in this post: http://silverlightdatagrid.com/CS/forums/permalink/31548/31516/ShowThread.aspx#31516.
Many users seem totally confused by your examples (which are largely out of date for .Net 4.0) and only target your own controls using the xcdg:CellEditorBinding which only seems to support PropertyChanged validation.
Unfortunately no solution was ever offered. He did present a strategy for changing the update source trigger more elegantly which I was able to adopt, but I still have the problem of the validation error freezing the cell until the user hits ESC.
<xcdg:AutoSelectTextBox Style="{StaticResource DefaultAutoSelectTextBox}"
Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=xcdg:DataCell},
Path=Content, UpdateSourceTrigger=LostFocus,
Converter={StaticResource EditablePercentageConverter}}" />
Update #3
I have confirmed that by updating to Xceed DataGrid version 4.3 (on trial), the problem went away all on its own, as in that version, Xceed updated its xcdg:CellEditorBinding
UpdateSourceTrigger
incompatibility with .Net4.0. Since, however, a license for Xceed only includes 6 months of bug fix updates before you have to pay for a whole new license (ridiculous), and I don't see any company authorizing an outrageous $1200 single developer license fee to use the latest Xceed dll just for this one minor bug, I'm still going to strive to find a complete workaround in the 3.7 version of Xceed. I'll present this 'solution' for the developers that have access to money to burn.
As it turns out, upgrading to 4.3 didn't solve the problem. It only appeared to because I'd forgotten to back out my previous change. Even in the latest version, Xceed still hasn't exposed the UpdateSourceTrigger
property on on CellEditorBinding
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
解决方案是:
确实没有其他方法可以做到这一点。如果您没有使用最新版本的 Xceed,这也会导致验证错误,但在最新版本中,使用这个新的绑定路径可以完美工作。我仍然认为这是一个 hack,希望 xceed 能够意识到它需要在其
CellEditorBinding
上公开更多属性。The solution is:
There's really no other way to do it. If you aren't using the latest version of Xceed, this will also lead to validation errors, but in the latest version, using this new binding path works perfectly. I still think it's a hack, and hopefully xceed will realize it needs to expose a few more properties on its
CellEditorBinding
.我不知道 XCeed 控件,所以这只是有根据的猜测。
我个人会将 UpdateSourceTrigger 放置到绑定声明中,就像在常规 .NET 控件中所做的那样:
此外,由于该控件是商业的,因此您应该有权获得 XCeed 的一些技术支持。
I don't know XCeed controls, so this is just educated guess.
I personally would place the UpdateSourceTrigger to the binding declaration like it is done in a regular .NET control:
Also, since the control is commercial, you should be entitled to some tech support from XCeed.