【发布时间】:2016-03-29 21:46:14
【问题描述】:
我很抱歉这么罗嗦,但我想让情况完全清楚。如果您是 WPF 专业人士,请看一下。
有两个CollectionViewSource 绑定到ItemsControls,它们使用UserControl 视图来显示StackPanels 或自定义Buttons。下面的屏幕截图中显示的每一侧都有一个。我遇到的问题是,当设置父集合属性时,DataTemplate 视图中的所有按钮都被禁用。即使是上面的 2 个按钮也有同样的问题,即使它们在我最近的编辑之前工作。
如果我单击表单或按任意键,按钮将启用。一旦属性重置为新编辑和排序的集合,它们就会再次禁用。冲洗并重复。这就是它的样子。第一帧是它的启动方式(灰色使用StackPanel),第二帧是单击 RFS 按钮时的样子,第三帧是我单击任意位置或按键时发生的情况。
我一直在兜圈子尝试一些事情。唯一似乎有效的是代码隐藏的解决方法,它将焦点集中在一件事上,然后再返回。但是,如果用户尝试使用其他仪表板项目之一,这对用户不利。
由于所有这些的 WPF 非常庞大,我将尝试仅包含相关部分。这些是 TabItemControl (UserControl) 上的 ItemsControls。
<!-- BID (SELL) DEPTH -->
<ItemsControl Grid.Row="0" Grid.Column="0" x:Name="bidDepthList" ItemsSource="{Binding Source={StaticResource BidDepthCollection}}"
Visibility="{Binding Path=IsMultilegEnabled, Converter={StaticResource CollapsedConverter}}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type viewmodels:DepthLevelViewModel}">
<v:DepthLevelRowView x:Name="BidDepthLevelRowViewControl" DataContext="{Binding}" HorizontalAlignment="Center" Margin="1,0,1,3" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<!-- ASK (BUY) DEPTH -->
<ItemsControl Grid.Row="0" Grid.Column="1" x:Name="askDepthList" ItemsSource="{Binding Source={StaticResource AskDepthCollection}}"
Visibility="{Binding Path=IsMultilegEnabled, Converter={StaticResource CollapsedConverter}}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type viewmodels:DepthLevelViewModel}">
<v:DepthLevelRowView x:Name="AskDepthLevelRowViewControl" DataContext="{Binding}" HorizontalAlignment="Center" Margin="1,0,1,3" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
正在使用的视图在网格内有 4 个“控件”。根据状态(RFS OFF/RFS ON)和它们在哪一侧(卖出/买入),一次只显示一个。其他人都崩溃了。如您所见,这很好。
它们之间唯一的共同点是它们设置了Command,顶部的大多数控件都正确禁用/启用。如果采取任何鼠标或键盘操作,按钮正确启用的事实告诉我CanExecute 处理程序正在工作,但不是立即工作。其他控件在我创建 these changes 后开始工作,但随后大按钮开始像深度按钮一样出现异常。
我在更改集合后尝试使用 CommandManager.InvalidateRequerySuggested();,但这没有帮助。
注意:即使是这样简单的事情也会发生这种情况:
<Button x:Name="TestBuyButton" Command="{x:Static ptcommands:OrderCommands.Buy}" CommandTarget="{Binding RelativeSource={RelativeSource Self}}" Content="Test Buy" />
我知道布尔值设置正确,因为我添加了测试 CheckBoxes 以使用 IsChecked 显示当前值。而且,一旦采取任何输入操作,它们都会启用,包括极其基本的 Button。
我还有什么遗漏或可以采取的不同方法吗?
编辑:我最终使用Dispatcher 从事件线程调用我的显示更新例程到 UI 线程。布尔值已设置,但 WPF 仍然没有重新查询 Command。但是.. CommandManager.InvalidateRequerySuggested() 电话然后起作用了!我唯一不喜欢的是它听起来像是广播失效。我不希望重新查询所有命令。我只想重新查询 Buy 和 Sell 命令。我已经尝试了各种奇怪的方法来让那些工作正常,但到目前为止除了全局之外没有任何工作。
编辑 2:似乎InvalidateRequerySuggested 是要走的路。
来自 MSDN CommandManager.InvalidateRequerySuggested:
CommandManager 在确定命令目标何时更改时仅关注某些条件,例如键盘焦点的更改。在 CommandManager 无法充分确定导致命令无法执行的条件变化的情况下,可以调用 InvalidateRequerySuggested 来强制 CommandManager 引发 RequerySuggested 事件。
这可以解释为什么焦点改变和按键会导致按钮启用。该页面还显示将呼叫置于计时器中。因此,我认为它不像我想象的那样占用资源。所以,我想这是我的永久解决方案。
【问题讨论】:
-
我做了another post 关于我在尝试解决此问题时所做的一些更改。由于它现在只填充一次并且只更新它所拥有的内容,因此它只被禁用一次。我可以单击表单,它不会再次禁用。我不知道当我再次添加/删除时是否会这样做,因为当前进程的填充速度非常快,然后会更改现有项目。因此,从技术上讲,禁用问题仍然存在。
-
我刚刚对这篇文章做了很大的修改以反映当前的情况。