WPF ComboBox:将 SelectedItem 设置为不在 ItemsSource 中的项目 ->绑定古怪 [英] WPF ComboBox: Set SelectedItem to item not in ItemsSource -> Binding oddity

查看:23
本文介绍了WPF ComboBox:将 SelectedItem 设置为不在 ItemsSource 中的项目 ->绑定古怪的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要实现以下目标:我想要一个显示可用 COM 端口的 ComboBox.在启动时(并单击刷新"按钮),我想获取可用的 COM 端口并将选择设置为上次选择的值(来自应用程序设置).

I want to achieve the following: I want to have a ComboBox which displays the available COM ports. On Startup (and clicking a "refresh" button) I want to get the available COM ports and set the selection to the last selected value (from the application settings).

如果设置中的值(最后一个 com 端口)不在值列表(可用的 COM 端口)中,则会发生以下情况:

If the value from the settings (last com port) is not in the list of values (available COM ports) following happens:

尽管 ComboBox 不显示任何内容(知道新的 SelectedItem 不在 ItemsSource 中已经足够聪明"),但 ViewModel 已更新为无效值".我实际上希望 Binding 具有与 ComboBox 显示相同的值.

Although the ComboBox doesn't display anything (it's "clever enough" to know that the new SelectedItem is not in ItemsSource), the ViewModel is updated with the "invalid value". I actually expected that the Binding has the same value which the ComboBox displays.

用于演示目的的代码:

MainWindow.xaml:

MainWindow.xaml:

    <Window x:Class="DemoComboBinding.MainWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            Title="MainWindow" Height="350" Width="525"
            xmlns:local="clr-namespace:DemoComboBinding">
        <Window.Resources>
            <local:DemoViewModel x:Key="vm" />
        </Window.Resources>
        <StackPanel Orientation="Vertical">
            <ComboBox SelectedItem="{Binding Source={StaticResource vm}, Path=Selected}" x:Name="combo"
            ItemsSource="{Binding Source={StaticResource vm}, Path=Source}"/>
            <Button Click="Button_Click">Set different</Button> <!-- would be refresh button -->
            <Label Content="{Binding Source={StaticResource vm}, Path=Selected}"/> <!-- shows the value from the view model -->
        </StackPanel>
    </Window>

MainWindow.xaml.cs:

MainWindow.xaml.cs:

    // usings removed
    namespace DemoComboBinding
    {
        public partial class MainWindow : Window
        {
            //...
            private void Button_Click(object sender, RoutedEventArgs e)
            {
                combo.SelectedItem = "COM4"; // would be setting from Properties
            }
        }
    }

视图模型:

    namespace DemoComboBinding
    {
        class DemoViewModel : INotifyPropertyChanged
        {
            string selected;

            string[] source = { "COM1", "COM2", "COM3" };

            public string[] Source
            {
                get { return source; }
                set { source = value; }
            }

            public string Selected
            {
                get { return selected; }
                set { 
                    if(selected != value)
                    {
                        selected = value;
                        OnpropertyChanged("Selected");
                    }
                }
            }

            #region INotifyPropertyChanged Members

            public event PropertyChangedEventHandler PropertyChanged;

            void OnpropertyChanged(string propertyname)
            {
                var handler = PropertyChanged;
                if(handler != null)
                {
                    handler(this, new PropertyChangedEventArgs(propertyname));
                }
            }

            #endregion
        }
    }

我最初想出的一个解决方案是检查 Selected setter 中要设置的值是否在可用 COM 端口列表中(如果不是,则设置为空字符串并发送 OPC).

A solution I initially came up with would be to check inside the Selected setter if the value to set is inside the list of available COM ports (if not, set to empty string and send OPC).

我想知道的是:为什么会这样?还有其他我没有看到的解决方案吗?

What I wonder: Why does that happen? Is there another solution I didn't see?

推荐答案

总之,您不能将SelectedItem 设置为ItemsSource 中没有的值.AFAIK,这是所有 的默认行为Selector 后代,这是相当明显的:设置 SelectedItem 不仅仅是一个数据变化,这也应该导致一些视觉效果,比如生成一个项目容器和重新绘制项目(所有这些操作ItemsSource).在这里你能做的最好的事情是这样的代码:

In short, you can't set SelectedItem to the value, that is not in ItemsSource. AFAIK, this is default behavior of all Selector descendants, which is rather obvious: settings SelectedItem isn't only a data changing, this also should lead to some visual consequences like generating an item container and re-drawing item (all those things manipulate ItemsSource). The best you can do here is code like this:

public DemoViewModel()
{
    selected = Source.FirstOrDefault(s => s == yourValueFromSettings);
}

另一个选项是允许用户通过使其可编辑来在 ComboBox 中输入任意值.

Another option is to allow user to enter arbitrary values in ComboBox by making it editable.

这篇关于WPF ComboBox:将 SelectedItem 设置为不在 ItemsSource 中的项目 ->绑定古怪的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆