更改setter中的SelectedItem值对组合框没有影响

本文关键字:组合 有影响 setter 中的 SelectedItem 更改 | 更新日期: 2023-09-27 18:26:46

我有一个ComboBox,它的SelectedItemItemsSource是绑定到视图模型的数据。无论何时选择"Blue",setter都会设置值"Green"并触发PropertyChanged事件。

在这种情况下,我希望ComboBox显示"Green",而显示的值保持为"Blue"

我已经对CheckBox进行了同样的尝试(绑定到IsChecked,无论何时将值设置为true并激发PropertyChanged,都会将其还原为false),并且它在那里可以正常工作。

MainWindow.xaml:

<Window x:Class="WpfTestApplication.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="80" Width="100">
    <Grid>
        <ComboBox x:Name="ComboBox" SelectedItem="{Binding SelectedItem}" ItemsSource="{Binding Values}" />
    </Grid>
</Window>

MainWindow.xaml.cs:

using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
namespace WpfTestApplication
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            ComboBox.DataContext = new ViewModel();
        }
    }
    public class ViewModel : INotifyPropertyChanged
    {
        public List<string> Values { get; set; } = new List<string>
        {
            "Green", "Red", "Blue"
        };
        public string SelectedItem
        {
            get { return selectedItem; }
            set
            {
                selectedItem = value;
                if (selectedItem == "Blue")
                    selectedItem = "Green";
                SelectedItemChanged();
            }
        }
        private string selectedItem = "Red";
        public event PropertyChangedEventHandler PropertyChanged;
        public void SelectedItemChanged() =>
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedItem)));
    }
}

更改setter中的SelectedItem值对组合框没有影响

这确实有点奇怪。事实证明,尽管组合框显示"蓝色",但它的SelectedItem现在声称是预期的"绿色"。我不知道为什么显示的值和可编程访问的SelectedItem值之间存在差异,但我确实找到了一个解决方法:

<ComboBox
    VerticalAlignment="Top"
    x:Name="ComboBox"
    SelectedItem="{Binding SelectedItem, Delay=1}"
    ItemsSource="{Binding Values}" />

Delay做到了,所以这里肯定有一些时间问题。

我试图创建一个适当的依赖属性,希望价值强制能起到作用:

public sealed partial class MainWindow
{
    private static readonly DependencyProperty SelectedItemProperty =
        DependencyProperty.Register(
            "SelectedItem",
            typeof(string),
            typeof(MainWindow),
            new PropertyMetadata("Red", SelectedItemChanged, SelectedItemCoerceValue));
    private static void SelectedItemChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
    }
    private static object SelectedItemCoerceValue(DependencyObject d, object basevalue)
    {
        if ("Blue".Equals(basevalue))
        {
            return "Green";
        }
        return basevalue;
    }
    public List<string> Values { get; set; } = new List<string>
        {
            "Green", "Red", "Blue",
        };
    public MainWindow()
    {
        InitializeComponent();
        ComboBox.DataContext = this;
    }
}

不幸的是,这个还需要Delay属性集。

您可以使用LostFocus作为UpdateSourceTrigger

<ComboBox
    VerticalAlignment="Top"
    x:Name="ComboBox"
    SelectedItem="{Binding SelectedItem, UpdateSourceTrigger=LostFocus}"
    ItemsSource="{Binding Values}" />