wpf - RibbonGallery.SelectedValue 不更新 SelectedItem
问题描述
我正在使用 Microsoft 功能区库:System.Windows.Controls.Ribbon
. 我知道这个问题看起来很大,但我想要做的实际上并没有那么复杂,只涉及到几个部分。
目标
我正在尝试将 a 的选择绑定到RibbonComboBox
我的一个类的属性,我将调用它TestBindingSource
,但我需要能够取消选择的更改。因此,如果他们从 中选择一个项目RibbonComboBox
,然后取消该更改,则选择需要保持原样。
显示的项目RibbonComboBox
代表 an 的成员Enum
,我将其称为TestEnum
。我构建了另一个类TestEnumGalleryItem
来表示 中的TestEnum
值,RibbonComboBox
并使用RibbonGallery.SelectedValue
andRibbonGallery.SelectedValuePath
绑定到 上的属性TestBindingSource
。如果这太难理解,您应该能够从我的代码中看到我的意思。
编码
下面是我的真实代码的简化版,尽量不要为了风格给我扣太多分。我已经在一个新项目中对此进行了测试,它可以用来显示我遇到的问题。请记住添加对 Microsoft 功能区库的引用。
主窗口.xaml
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:VBTest"
mc:Ignorable="d"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Ribbon>
<RibbonTab Header="Test">
<RibbonGroup>
<RibbonComboBox Name="TestComboBox">
<RibbonGallery Name="TestGallery" MaxColumnCount="1" ScrollViewer.VerticalScrollBarVisibility="Auto" SelectedValuePath="EnumValue" SelectedValue="{Binding BindingSource.TestEnumValue}">
<RibbonGallery.ItemsSource>
<x:Array Type="local:TestEnumGalleryCategory">
<local:TestEnumGalleryCategory/>
</x:Array>
</RibbonGallery.ItemsSource>
<RibbonGallery.CategoryTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Items}">
<HierarchicalDataTemplate.ItemTemplate>
<DataTemplate>
<RibbonGalleryItem ToolTipTitle="{Binding EnumName}" ToolTipDescription="{Binding EnumDescription}">
<TextBlock Text="{Binding EnumName}" Margin="0, -3, -0, -3"/>
</RibbonGalleryItem>
</DataTemplate>
</HierarchicalDataTemplate.ItemTemplate>
</HierarchicalDataTemplate>
</RibbonGallery.CategoryTemplate>
</RibbonGallery>
</RibbonComboBox>
<RibbonButton Label="Break" Click="RibbonButton_Click"/>
</RibbonGroup>
</RibbonTab>
</Ribbon>
</Grid>
</Window>
主窗口.xaml.vb
Imports System.ComponentModel
Class MainWindow
Public Sub New()
BindingSource = New TestBindingSource
InitializeComponent()
End Sub
Public Property BindingSource As TestBindingSource
Get
Return GetValue(BindingSourceProperty)
End Get
Set(ByVal value As TestBindingSource)
SetValue(BindingSourceProperty, value)
End Set
End Property
Public Shared ReadOnly BindingSourceProperty As DependencyProperty =
DependencyProperty.Register("BindingSource",
GetType(TestBindingSource), GetType(MainWindow))
Private Sub RibbonButton_Click(sender As Object, e As RoutedEventArgs)
Stop
End Sub
End Class
Public Enum TestEnum
ValueA
ValueB
End Enum
Public Class TestEnumGalleryCategory
Public Property Items As New List(Of TestEnumGalleryItem) From {New TestEnumGalleryItem With {.EnumValue = TestEnum.ValueA, .EnumName = "Value A", .EnumDescription = "A's description"},
New TestEnumGalleryItem With {.EnumValue = TestEnum.ValueB, .EnumName = "Value B", .EnumDescription = "B's description"}}
End Class
Public Class TestEnumGalleryItem
Public Property EnumValue As TestEnum = TestEnum.ValueA
Public Property EnumName As String
Public Property EnumDescription As String
End Class
Public Class TestBindingSource
Implements INotifyPropertyChanged
Private _TestEnumValue As TestEnum = TestEnum.ValueA
Property TestEnumValue As TestEnum
Get
Return _TestEnumValue
End Get
Set(value As TestEnum)
'Don't actually set new value, just leave it the same to simulate cancelation
RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(NameOf(TestEnumValue)))
End Set
End Property
Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged
End Class
问题
当您运行代码时,您会看到RibbonComboBox
默认情况下显示“值 A”。将选择更改为“值 B”。更改的选择RibbonComboBox
现在显示“值 B”。这不是我想要发生的,选择应该立即变回“值 A”。
如果您查看 的代码TestBindingSource.TestEnumValue
,您会发现设置时我实际上并没有保留新值,而是保留旧值以模拟用户取消更改。然后我引发PropertyChanged
事件以更新 UI,以便它知道属性的真正价值是什么。
更改为“Value B”后,单击“Break”按钮(为方便起见包括在内)。在 Visual Studio 监视窗口中,比较 和 的TestGallery.SelectedItem
值TestGallery.SelectedValue
。你会看到它TestGallery.SelectedValue
拥有正确的TestEnum
值ValueA
。现在看一下TestGallery.SelectedItem
,您会发现它仍然包含表示 的项目ValueB
。
因此,即使RibbonGallery
已正确告知该值现在应该是ValueA
,它仍然显示ValueB
。我该如何解决?
我会跟你讲道理,我没有太多时间花在这个 bug 上,而且我已经习惯了在涉及到功能区时不得不做出一些变通的解决方法。您可以为我提供有关如何
正确更新RibbonGallery
(以及因此RibbonComboBox
)正确更新的任何解决方案,我们将不胜感激。
解决方案
经过更多的测试和研究,我意识到这个问题并不是功能区库所独有的。实际上,这似乎也是正常的问题,ComboBox
大概是所有的问题ItemsControls
。一旦我意识到这一点,我就能够更有效地寻找答案并在这里找到解决方案:
https ://nathan.alner.net/2010/04/25/cancelling-selection-change-in-a-bound-wpf -组合框/
这不是一个完全干净的解决方案,但在我的具体情况下,将值设置为新选择然后立即将其设置回不会导致任何问题,所以我就是这样做的。作为记录,在重新设置选择时,我使用DispatcherPriority.DataBind
而不是DispatcherPriority.ContextIdle
,这样更改甚至不会显示在 UI 中,但解决方案仍然有效。
推荐阅读
- javascript - React.js 仅在单击选项卡后才看到选项卡名称?
- java - JPA插入身份ID从0而不是1开始?
- python - 混淆矩阵和分类报告
- c - 如何在 C 中泛化函数
- javascript - 在 Firebase 实时数据库中观察同一节点的多个子节点
- arrays - Ruby:如何在数组中逐个比较元素?
- amazon-sagemaker - 成功训练后 AWS Sagemaker 失败“ClientError: Artifact upload failed:Insufficient disk space”
- c# - cookie 过期后从 Identity 注销会导致 http 错误 400
- sql - 如果未找到数据,则匹配第 1 列,然后搜索第 2 列 oracle 查询
- bash - 为什么 bash 中的 read 命令可以使用 herestring,但不能使用管道输出?