Я использую ленточную библиотеку Microsoft: System.Windows.Controls.Ribbon
. Я знаю, что этот вопрос выглядит большим, но то, что я пытаюсь сделать, на самом деле не так уж сложно, в нем участвуют всего несколько частей.
Цель
Я пытаюсь связатьвыбор RibbonComboBox
для свойства одного из моих классов, который я назову TestBindingSource
, но мне нужно иметь возможность отменить изменение выбора. Поэтому, если они выбирают элемент из RibbonComboBox
, но затем отменяют это изменение, выбор должен оставаться таким, как был.
Элементы, отображаемые в RibbonComboBox
, представляют членов Enum
,который я назову TestEnum
. Я создал еще один класс TestEnumGalleryItem
для представления значений TestEnum
в RibbonComboBox
, и я использую RibbonGallery.SelectedValue
и RibbonGallery.SelectedValuePath
для привязки к свойству в TestBindingSource
. В случае, если за этим было слишком трудно следить, вы сможете понять, что я имею в виду из моего кода.
Код
Ниже приведена упрощенная версия моего реального кода, постарайтесь неПрикрепите мне слишком много очков для стиля. Я проверил это в новом проекте, и его можно использовать, чтобы показать проблему, с которой я столкнулся. Не забудьте добавить ссылку на ленточную библиотеку Microsoft.
MainWindow.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>
MainWindow.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». Это не то, чего я хочу, выбор должен немедленно измениться на «Значение А.».
Если вы посмотрите на код для TestBindingSource.TestEnumValue
, вы увидите, что я на самом деле не сохраняюпри установке нового значения, вместо этого я оставляю старое для имитации отмены изменения пользователем. Затем я вызываю событие PropertyChanged
, чтобы обновить пользовательский интерфейс, чтобы он знал реальное значение свойства.
После того, как вы изменили значение «Значение B», нажмите кнопку «Разрыв» (включена дляудобство). В окне просмотра Visual Studio сравните значения TestGallery.SelectedItem
и TestGallery.SelectedValue
. Вы увидите, что TestGallery.SelectedValue
содержит правильное TestEnum
значение ValueA
. Теперь посмотрите на TestGallery.SelectedItem
, и вы увидите, что он по-прежнему содержит элемент, представляющий ValueB
.
Так что, хотя RibbonGallery
был должным образом проинформирован, что значение теперь должно быть ValueA
, этовсе еще показывает ValueB
. Как я могу это исправить?
Я буду на одном уровне с вами, у меня нет тонны времени, чтобы тратить на эту ошибку, и я привык делать хакерские обходные пути, когда дело доходит доленты. Будем благодарны за любое решение, которое вы можете дать мне, как правильно настроить RibbonGallery
(и, следовательно, RibbonComboBox
).