【问题标题】:Set ComboBox SelectedItem to dataobject not present in ItemSource将 ComboBox SelectedItem 设置为 ItemSource 中不存在的数据对象
【发布时间】:2011-03-20 23:46:26
【问题描述】:

我有一个组合框,其 SelectedItem 和 ItemSource 属性绑定到视图模型。 ItemSource 中的对象是时间敏感的,因为对象过期,我只能将集合中的活动项目设置为 ItemSource。现在在某个时刻,selectedItem 对象可能不在 ItemSource 中。 我认为 ItemSource 的正常行为是只允许从 ItemSource 集合中选择对象,但在这种情况下,我确实想选择一个不再在 ItemSource 中的对象。 我该如何实现这种行为?我将在这里发布一些代码来支持我的问题。

Window.xaml

 <Window x:Class="ExpiredSelectedItem.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">
<Grid>
    <ComboBox Height="23" 
              HorizontalAlignment="Left" 
              Margin="184,68,0,0" 
              Name="comboBox1" 
              VerticalAlignment="Top" 
              Width="120" 
              ItemsSource="{Binding CustomList}"
              SelectedItem="{Binding ActiveItem}"
              SelectedValue="Code"
              SelectedValuePath="{Binding ActiveItem.Code}"
              DisplayMemberPath="Code"
              />
</Grid>

Window.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace ExpiredSelectedItem
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        CustomList = new List<DomainObject>();

        CustomList.AddRange(new DomainObject[] {
            new DomainObject() { Code = "A", IsActive =true},
            new DomainObject() { Code ="B", IsActive = true},
            new DomainObject() { Code = "C", IsActive =true},
        });

        ActiveItem = new DomainObject() { Code = "D", IsActive = false };

        this.DataContext = this;
    }


    public List<DomainObject> CustomList { get; set; }

    public DomainObject ActiveItem { get; set; }
}

public class DomainObject
{
    public string Code { get; set; }
    public bool IsActive { get; set; }

}

}

即使我在代码隐藏中选择了代码 D,当组合框加载时,第一个项目 (A) 也被选中。预期的行为是应该在文本框中选择“D”,但在打开下拉菜单时不应该有任何项目。

【问题讨论】:

    标签: wpf combobox selecteditem


    【解决方案1】:

    我不知道这是否起到任何作用,但它确实看起来很可疑。尝试删除它:

    <ComboBox ... SelectedValue="Code" ...
    

    【讨论】:

    • 感谢 Jon 指出这一点 - selectedValue 和 selectedvaluePath 用于不同的目的,在此示例中只是噪音。但是,这并不能解决问题。现在不是第一个项目被选中,所选文本显示为空白。正如上面帖子中提到的,我希望选择“D”。
    【解决方案2】:

    要保留不在列表中的选定项目,您可以执行以下操作:

    • 防止 ActiveItem 设置为 NULL;请参阅:if (value != null)
    • 清除组合框;见:comboBox1.SelectedIndex = -1;
    • 实施 INotifyPropertyChanged(您可能已经这样做了)

    这些更改可能会导致您的代码弊大于利,但希望这可以帮助您入门。

    下面是代码:

    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Windows;
    
    namespace ComboBoxSelectedItem
    {
      public partial class MainWindow : Window, INotifyPropertyChanged
      {
        public event PropertyChangedEventHandler PropertyChanged;
        void Notify(string propName)
        {
          if (PropertyChanged != null)
          {
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
          }
        }
    
        public MainWindow()
        {
          InitializeComponent();
    
          CustomList = new List<DomainObject>();
    
          CustomList.AddRange(new DomainObject[] {
            new DomainObject() { Code = "A", IsActive =true},
            new DomainObject() { Code ="B", IsActive = true},
            new DomainObject() { Code = "C", IsActive =true},
            });
    
          this.DataContext = this;
        }
    
        public List<DomainObject> CustomList { get; set; }
    
        private DomainObject _activeItem = new DomainObject() { Code = "D", IsActive = false };
        public DomainObject ActiveItem 
        {
          get { return _activeItem; }
          set
          {
            if (value != null)
            {
              _activeItem = value;
            }
    
            Notify("ActiveItem");
          }
        }
    
        private void Button_Click(object sender, RoutedEventArgs e)
        {
          ActiveItem = new DomainObject() { Code = "D", IsActive = false };
          comboBox1.SelectedIndex = -1;
        }
      }
    }
    

    这是 XAML:

    <Window x:Class="ComboBoxSelectedItem.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">
      <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <ComboBox 
            Grid.Row="0"
            Height="23" 
            HorizontalAlignment="Left" 
            Name="comboBox1" 
            VerticalAlignment="Top" 
            Width="120" 
            ItemsSource="{Binding CustomList}"
            SelectedItem="{Binding ActiveItem}"
            DisplayMemberPath="Code"/>
        <TextBox 
            Grid.Row="1"
            Text="{Binding Path=ActiveItem.Code, Mode=TwoWay}"/>
        <Button 
            Grid.Row="2" 
            Content="D" 
            Click="Button_Click"/>
      </Grid>
    </Window>
    

    【讨论】:

      猜你喜欢
      • 2019-02-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-23
      • 2015-11-16
      • 2023-03-09
      • 1970-01-01
      相关资源
      最近更新 更多