RibbonGallery.SelectedValue不更新 SelectedItem

问题描述 投票:0回答:1

我正在使用Microsoft功能区库:System.Windows.Controls.Ribbon。我知道这个问题看起来很重要,但是我实际上想做的并不那么复杂,只涉及几部分。

目标

我正在尝试将RibbonComboBox的选择绑定到我的一个类的属性上,我将其称为TestBindingSource,但是我需要能够取消选择的更改。因此,如果他们从RibbonComboBox中选择一项,然后取消该更改,则选择必须保持原样。

RibbonComboBox中显示的项目代表Enum的成员,我将其称为TestEnum。我建立了另一个类TestEnumGalleryItem来表示TestEnum中的RibbonComboBox值,然后使用RibbonGallery.SelectedValueRibbonGallery.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”。这不是我要发生的情况,选择应立即更改回“值A”。

[如果您查看TestBindingSource.TestEnumValue的代码,您会发现设置时实际上并没有保留新值,而是让旧值模拟用户取消更改。然后,我引发PropertyChanged事件以更新UI,以便它知道该属性的实际值是什么。

更改为“值B”后,单击“中断”按钮(为方便起见已包括在内)。在Visual Studio监视窗口中,比较TestGallery.SelectedItemTestGallery.SelectedValue的值。您会看到TestGallery.SelectedValue保持正确的TestEnumValueA。现在查看TestGallery.SelectedItem,您将看到它仍然保留代表ValueB的项目。

因此,即使RibbonGallery已被正确告知该值现在应为ValueA,它仍显示ValueB。我该如何解决?

我会与您保持联系,我没有太多时间花在这个错误上,而且我习惯在功能区上不得不采取一些棘手的解决方法。您可以给我任何解决方案的方法RibbonGallery(因此RibbonComboBox)可以正确更新。

wpf vb.net data-binding ribbon
1个回答
0
投票

经过更多的测试和研究,我意识到此问题并非功能区库所独有。实际上,正常的ComboBox似乎也可能是所有ItemsControls的问题。一旦意识到这一点,便能够更有效地寻找答案,并在此处找到解决方案:https://nathan.alner.net/2010/04/25/cancelling-selection-change-in-a-bound-wpf-combo-box/

这不是一个完美的解决方案,但是在我的特定情况下,将值设置为新选择,然后立即将其重新设置不会造成任何问题,所以我就是这样做的。作为记录,当重新设置选择时,我使用了DispatcherPriority.DataBind而不是DispatcherPriority.ContextIdle,这样,更改甚至都不会显示在UI中,但是解决方案仍然有效。

© www.soinside.com 2019 - 2024. All rights reserved.