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

查看:239
本文介绍了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
            }
        }
    }

ViewModel:

ViewModel:

    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
        }
    }

我最初想出的解决方案是检查选定的设置器"内部是否要设置的值在可用的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中的项目-&gt;绑定奇数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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