为什么这个简单的数据绑定方案不起作用? (ComboBox相关)

时间:2009-01-19 18:34:09

标签: silverlight data-binding combobox selecteditem itemssource

我现在已经在这个问题上摸不着头脑了,此刻我很难过。

问题场景更容易解释为代码,所以希望它能说明问题。首先,我在XAML中有以下的Silverlight应用程序...

<UserControl x:Class="SilverlightApplication2.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
Width="400" Height="300">

<UserControl.Resources>
    <DataTemplate x:Key="icTemplate">
        <ComboBox ItemsSource="{Binding StringsChild}" SelectedItem="{Binding SelectedItem}"/>
    </DataTemplate>
</UserControl.Resources>

<Grid x:Name="LayoutRoot" Background="White">
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <ItemsControl x:Name="ic" ItemTemplate="{StaticResource icTemplate}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel Orientation="Vertical"/>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>

    <Button Click="Save" Grid.Row="1" Content="GO"/>
</Grid>

我的代码隐藏看起来像这样......(所有代码都写在单个类文件中,因此您可以轻松地将其复制到您自己的项目中并进行编译)

namespace SilverlightApplication2
{
    public partial class Page : UserControl
    {
        public ObservableCollection<SomeClass> StringsParent { get; set; } 

        public Page()
        {   
            InitializeComponent();
            StringsParent = new ObservableCollection<SomeClass>();
            ic.ItemsSource = StringsParent;
        }

        private void Save(object sender, RoutedEventArgs e)
        {
            SomeClass c = new SomeClass();
            c.StringsChild.Add("First");
            c.StringsChild.Add("Second");
            c.StringsChild.SetSelectedItem("Second");
            StringsParent.Add(c);
        }
    }

    public class SomeClass
    {
        public SelectableObservablecollection<string> StringsChild { get; set; }

        public SomeClass()
        {
            StringsChild = new SelectableObservablecollection<string>();
        }    
    }

    public class SelectableObservablecollection<T> : ObservableCollection<T>
    {
        public SelectableObservablecollection()
            : base()
        {

        }

        public void SetSelectedItem<Q>(Q selectedItem)
        {
            foreach (T item in this)
            {
                if (item.Equals(selectedItem))
                {
                    SelectedItem = item;
                    return;
                }
            }
        }

        private T _selectedItem;
        public T SelectedItem
        {
            get
            {
                return _selectedItem;
            }
            set
            {
                _selectedItem = value;
                OnPropertyChanged(new PropertyChangedEventArgs("SelectedItem"));
            }
        }
    }
}

所以让我解释一下...... 我开始编写一个创建ObservableCollection的通用方法,它具有 SelectedItem 属性,这样当我将集合绑定到ComboBox时,我可以绑定ComboBox的 SelectedItem 属性。

但是,出于某种原因,当ComboBox通过ItemTemplate有效嵌套时,它似乎不起作用。我实际上有一个列表列表,这个场景很简单,我错了。

当你运行代码时,你会发现模板化的ComboBox确实拾取了正确的项目,但是尽管有绑定,它仍然不会被设置为SelectedItem。

我知道它很长,但是......任何想法?

非常感谢

1 个答案:

答案 0 :(得分:3)

调试器输出实际上为您提供了一个问题提示:

System.Windows.Data错误:BindingExpression路径错误:'SelectedItem'属性未在'ExpressionElements.SomeClass'上找到'ExpressionElements.SomeClass'(HashCode = 49044892)。 BindingExpression:Path ='SelectedItem'DataItem ='ExpressionElements.SomeClass'(HashCode = 49044892); target元素是'System.Windows.Controls.ComboBox'(Name =''); target属性是'SelectedItem'(类型'System.Object')..

因为模板的Data上下文是SomeClass类的实例,所以您只需将SelectedItem绑定从SelectedItem更改为 StringsChild.SelectedItem

<DataTemplate x:Key="icTemplate">
    <ComboBox ItemsSource="{Binding StringsChild}" 
     SelectedItem="{Binding StringsChild.SelectedItem}"/>
</DataTemplate>