首页 文章

WPF ComboBox绑定到UserControls的集合不显示所选项目的文本

提问于
浏览
0

我有一个ComboBox绑定到自定义UserControls的ObservableCollection . 每个用户控件都设置了Tag值,ComboBox的DisplayMemberPath设置为“Tag” . 单击ComboBox时,这会在下拉列表中正确显示每个UserControl的标记,但是当选择列表中的项目并关闭下拉列表时,ComboBox不会在按钮中显示任何内容 .

如果我将UserControl替换为标准WPF控件(如TextBox),则它会正确显示所选项的Tag值,因此它与绑定到UserControl与标准WPF控件相关 . 此外,如果我将IsEditable设置为True,则可编辑的TextBox会正确显示标记,但我不希望文本可编辑 .

如何在未展开ComboBox时显示Selected项目?

以下是一些复制问题的示例代码:

(注意:示例代码是从它运行的应用程序的上下文中取出的,因此它在尝试执行的操作中看起来有点奇怪,但它仍会导致相同的症状) .

MyUC.xaml

<UserControl x:Class="ComboboxTest.MyUC"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid>
        <TextBox />
    </Grid>
</UserControl>

Window1.xaml

<Window x:Class="ComboboxTest.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:ComboboxTest"
        Title="Window1" Height="300" Width="300"
        DataContext="{Binding RelativeSource={RelativeSource Self}}">
<StackPanel>
    <StackPanel Name="ControlsHolder">
        <TextBox Tag="Box 1" Text="This is in Box 1" />
        <TextBox Tag="Box 2" Text="This is in Box 2" />
        <local:MyUC Tag="UC 1" />
        <local:MyUC Tag="UC 2" />
    </StackPanel>
    <Grid>
        <ComboBox Grid.Column="1" 
              Margin="5,0" 
              Name="MyComboBox" 
              ItemsSource="{Binding MyControls}"
              DisplayMemberPath="Tag" 
              MinWidth="120"/>
    </Grid>
</StackPanel>

Window1.cs

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

namespace ComboboxTest
{
    public partial class Window1 : Window, INotifyPropertyChanged
    {
        ObservableCollection<MyUC> myControls = new ObservableCollection<MyUC>();

        public Window1()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(Window1_Loaded);
        }

        void Window1_Loaded(object sender, RoutedEventArgs e)
        {
            myControls.Clear();

            foreach (UIElement uiElement in this.ControlsHolder.Children)
            {
                MyUC tb = uiElement as MyUC;

                if (tb != null)
                {
                    myControls.Add(tb);
                }
            }

            RaisePropertyChanged("MyControls");
        }

        public ObservableCollection<MyUC> MyControls
        {
            get
            {
                return this.myControls;
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void RaisePropertyChanged(string p)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(p));
            }
        }
    }
}

此应用程序显示为:ComboBox with Drop Down Visible http://img229.imageshack.us/img229/5597/comboboxtestexpanded.png

选择"UC 2"时,它显示为:ComboBox with selected item not visible http://img692.imageshack.us/img692/4362/comboboxtestuc2selected.png

1 回答

  • 1

    绑定 UIElements 列表不是一个好主意 . 尝试使用包装类:

    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(Window1_Loaded);
            MyComboBox.ItemsSource = MyControls;
        }
    
        ObservableCollection<Wrapper> myControls = new ObservableCollection<Wrapper>();
    
        void Window1_Loaded(object sender, RoutedEventArgs e)
        {
            myControls.Clear();
    
            foreach (UIElement uiElement in this.ControlsHolder.Children)
            {
                MyUC tb = uiElement as MyUC;
    
                if (tb != null)
                {
                    myControls.Add(new Wrapper(tb));
                }
            }
    
            RaisePropertyChanged("MyControls");
        }
    
        public ObservableCollection<Wrapper> MyControls
        {
            get
            {
                return this.myControls;
            }
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
        private void RaisePropertyChanged(string p)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(p));
            }
        }
    }
    
    public class Wrapper
    {
        public UserControl Control { get; protected set; }
    
        public Wrapper(UserControl control)
        {
            Control = control;
        }
    
        public Object Tag
        {
            get { return Control.Tag; }
        }
    }
    

相关问题