如何在C#中更改ComboBox的itemsSource

时间:2013-10-04 19:52:10

标签: c# wpf data-binding combobox

我正在尝试在运行时更改itemsSource的{​​{1}}。在this question我被告知要做comboBox。如果我需要做的就是创建一个新的comboBox.itemssource...,然后在其上调用命令,那就没关系。但是,我需要通过xaml在我的用户控件中已存在的comboBox上执行此操作。在那种情况下,我将如何引用它?我知道如何绑定到控件中的属性,但在这种情况下,我需要获得整个控件。我是在过度思考吗?做我想的最好的方法是什么?

这是我目前如何在comboBox中切换收藏集(这是模型级别的所有收藏):

comboBox

使用此实现时,集合会切换,但//Property for Combo Box List public ObservableCollection<string> ComboBoxList { get { return _comboBoxList; } set { if (Equals(value, _comboBoxList)) return; _comboBoxList = value; OnPropertyChanged("ComboBoxList"); } } public string SelectedCommand { get { return _selectedCommand; } set { _selectedCommand = value; NotifyPropertyChange(() => SelectedCommand); if (SelectedCommand == "String Value") { ComboBoxList = new ObservableCollection<string>(newList); } } } 中的selectedItem不会停留。例如,当我单击其他命令然后切换回来时,该框不再具有comboBox

更新

我有一个名为selectedItem的属性绑定到我的selectedOperation。它包含一个简单的getter和setter,带有comboBox。这使得框中的NotifyPropertyChange保持选中状态。但是,如果用户点击其他命令并选择selectedItem中的其他项目,则该新项目会将其取代。我需要为comboBox拥有的每个集合设置selectedItem

例如:

假设comboBox,A和B中有2个命令。每个命令在listBox中创建一个不同的集合。 A创建一个数字集合,B创建一个名称集合。

对于命令A,用户选择5.当选择A时,comboBox应显示5,因为它是comboBox。 A - &gt; 5

对于命令B,用户选择Roger。选择B后,selectedItem应显示“Roger”,因为它是comboBox。 B - &gt;罗杰

目前,当用户在命令之间切换时,selectedItem不记得comboBox

2 个答案:

答案 0 :(得分:3)

我宁愿使用DataContext并更新该来源,也不要手动更新ComboBox.ItemsSource属性。

这样就根本不需要了解控件。

这是一个小例子:

当用户点击该按钮时,您只需要处理更新数据,而不是更新数据。

<Window x:Class="WpfApplication10.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" x:Name="Window1">
    <Grid DataContext="{Binding ElementName=Window1}">
        <StackPanel>
            <Button Click="Button_Click">Some data 1</Button>
            <Button Click="Button_Click_1">Some data 2</Button>
            <ListBox x:Name="ComboBox1" ItemsSource="{Binding Collection}"></ListBox>
        </StackPanel>
    </Grid>
</Window>
using System.Collections.ObjectModel;
using System.Windows;

namespace WpfApplication10
{
    /// <summary>
    ///     Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        private readonly ObservableCollection<string> _collection = new ObservableCollection<string>();

        public MainWindow()
        {
            InitializeComponent();
        }

        public ObservableCollection<string> Collection
        {
            get { return _collection; }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            _collection.Clear();
            for (int i = 0; i < 5; i++)
            {
                _collection.Add("method 1 item " + i);
            }
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {  _collection.Clear();
            for (int i = 0; i < 5; i++)
            {
                _collection.Add("method 2 item " + i);
            }
        }
    }
}

<强>更新

如果您想使用新集合而不是删除项目,则必须为集合实现INotifyPropertyChanged。

using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;

namespace WpfApplication10
{
    /// <summary>
    ///     Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        private ObservableCollection<string> _collection = new ObservableCollection<string>();

        public MainWindow()
        {
            InitializeComponent();
        }

        public ObservableCollection<string> Collection
        {
            get { return _collection; }
            set
            {
                if (Equals(value, _collection)) return;
                _collection = value;
                OnPropertyChanged();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Collection = new ObservableCollection<string>(new[] {"1", "2"});
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            Collection = new ObservableCollection<string>(new[] {"3", "4"});
        }

        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

注意:每次调用invocator时,[CallerMemberName]都会使您免于添加属性名称,但如果我没记错的话,它只能用于.NET 4.5。

如果您不在.NET 4.5之下,那么您必须改为OnPropertyChanged("Collection")

参考:INotifyPropertyChanged

此外,使用新集合更新Collection,而不是_collection,否则您的用户界面将不会收到通知。

编辑2

您需要根据使用的集合跟踪所选项目。

<Window x:Class="WpfApplication10.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" x:Name="Window1">
    <Grid>
        <StackPanel>
            <Button Click="Button_Click">Some data 1</Button>
            <Button Click="Button_Click_1">Some data 2</Button>
            <ListBox x:Name="ComboBox1" ItemsSource="{Binding}" SelectedItem="{Binding MySelectedItem}" />
        </StackPanel>
    </Grid>
</Window>

代码背后:

using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows;

namespace WpfApplication10
{
    public partial class MainWindow
    {
        public MainWindow()
        {
            InitializeComponent();

            MyCustomCollection1 = new MyCustomCollection<string>(new[] {"a", "b"});
            MyCustomCollection2 = new MyCustomCollection<string>(new[] {"c", "d"});
        }

        public MyCustomCollection<string> MyCustomCollection1 { get; set; }

        public MyCustomCollection<string> MyCustomCollection2 { get; set; }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            DataContext = MyCustomCollection1;
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            DataContext = MyCustomCollection2;
        }
    }

    public class MyCustomCollection<T> : ObservableCollection<T>
    {
        private T _mySelectedItem;

        public MyCustomCollection(IEnumerable<T> collection) : base(collection)
        {
        }

        public T MySelectedItem
        {
            get { return _mySelectedItem; }
            set
            {
                if (Equals(value, _mySelectedItem))return;
                _mySelectedItem = value;
                OnPropertyChanged(new PropertyChangedEventArgs("MySelectedItem"));
            }
        }
    }
}

答案 1 :(得分:0)

尝试使用一些触发器(可以是任何触发器数据/事件)通过样式更改集合这里是一个例子:

<Style x:Key="MySelectItemSourceStyle" TargetType="ComboBox">
    <Setter Property="ItemsSource" Value="{Binding Collection1}" />
    <Style.Triggers>
       <DataTrigger Binding="{Binding SomeValue}" Value="SecondCollection">
          <Setter Property="ItemsSource" Value="{Binding Collection2}" />
       </DataTrigger>
    </Style.Triggers>
</Style>