完全在XAML中绑定ComboBox

时间:2011-04-13 04:35:43

标签: silverlight binding

我在Silverlight控件上有一个ComboBox,我想要绑定。听起来很简单,除了我发现的是因为ItemsSource的数据异步来自Web服务,我需要使用后面的代码仅在数据返回后绑定SelectedValue。

数据进入的集合实现了INotifyCollectionChanged和INotifyPropertyChanged,因此它应该全部正常工作,实际上组合框正确加载,但没有预先选择的值。

我认为发生的事情是SelectedValue在加载集合之前被绑定 - 当组合框为空时 - 因此没有选择任何内容,然后当数据进入时,组合框被填充,但它不是再次检查所选值。

因此,如果我使用后面的代码来连接事件并在代码中创建绑定,那么我有这个工作,我想把这一切都转移到XAML,例如:

<ComboBox HorizontalAlignment="Stretch" Margin="5,3,9,127" Name="cboCategoryID"  Grid.Row="4" Grid.Column="1"
           ItemsSource="{StaticResource Categories}"
           SelectedValue="{Binding CategoryID, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnDataErrors=True}" 
           SelectedValuePath="CategoryID" 
           DisplayMemberPath="Caption"
           VerticalAlignment="Center">
</ComboBox>

这会正确加载项目,但不会绑定所选值。如果我将以下代码放在代码隐藏中,那么一切正常:

public MainControl()
{
    InitializeComponent();

    CategoryCollection cats = new CategoryCollection();
    cats.Dispatcher = this.Dispatcher;
    cats.LoadComplete += new EventHandler(cats_LoadComplete);
    cboCategoryID.ItemsSource = cats;
    cats.LoadAll();
}

private void cats_LoadComplete(object sender, EventArgs e)
{
    cboCategoryID.SetBinding(ComboBox.SelectedValueProperty, new System.Windows.Data.Binding("CategoryID"));
}

有没有办法在不诉诸代码的情况下做到这一点?

3 个答案:

答案 0 :(得分:0)

您使用的是mvvm吗?如果是这样,您可以尝试在Web服务的回调中设置ItemsSource和SelectedItem,或者查看Kyle的这篇文章。

http://blogs.msdn.com/b/kylemc/archive/2010/06/18/combobox-sample-for-ria-services.aspx

答案 1 :(得分:0)

您已经在使用一个通知更改的集合,因此如果您绑定SelectedValue的值是通知更改,那么您需要做的就是在从Web服务加载值之后设置该属性。它应该自动更新组合框,允许你纯粹在xaml中进行绑定。

public myObject CategoryID { get {....} 
                             set {
                              this.categoryID = value;
                              RaisePropertyChanged("CategoryID");}


public void DataLoadedHandler()
{
    CategoryID = 34; // this will cause the binding to update
}

答案 2 :(得分:0)

看看这个简单的样本: XAML:

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:sdk="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data" xmlns:local="clr-namespace:StackoverflowQuestions.Silverlight" xmlns:sdk1="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" x:Class="StackoverflowQuestions.Silverlight.MainPage"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <UserControl.Resources>
        <DataTemplate x:Key="Item">
            <TextBlock Text="{Binding PropertyToBeWatched}" />
        </DataTemplate>
    </UserControl.Resources>

    <Grid x:Name="LayoutRoot" Background="White">
        <!--<sdk:DataGrid ItemsSource="{Binding MyList}" RowStyle="{StaticResource Style1}">
            <sdk:DataGrid.Columns>
                <sdk:DataGridTextColumn Binding="{Binding PropertyToBeWatched}" Header="Property1"/>
            </sdk:DataGrid.Columns>
        </sdk:DataGrid>-->
        <ComboBox ItemsSource="{Binding MyList}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" Height="50" VerticalAlignment="Top" ItemTemplate="{StaticResource Item}" />
    </Grid>
</UserControl> 

代码隐藏:     public partial class MainPage:UserControl,INotifyPropertyChanged         {             private ObservableCollection _myList;             private CustomClass _selectedItem;

        public event PropertyChangedEventHandler PropertyChanged;

        public ObservableCollection<CustomClass> MyList
        {
            get { return _myList ?? (_myList = new ObservableCollection<CustomClass>()); }
            set
            {
                _myList = value;
                RaisePropertyChanged("MyList");
            }
        }

        public CustomClass SelectedItem
        {
            get { return _selectedItem; }
            set
            {
                _selectedItem = value;
                RaisePropertyChanged("SelectedItem");
            }
        }

        protected void RaisePropertyChanged(string propertyname)
        {
            var handler = PropertyChanged;
            if (handler != null)
                handler(this, new PropertyChangedEventArgs(propertyname));
        }

        public MainPage()
        {
            InitializeComponent();
            this.DataContext = this;

            MyList.Add(new CustomClass() { PropertyToBeWatched = "1"});
            MyList.Add(new CustomClass() { PropertyToBeWatched = "2" });
            MyList.Add(new CustomClass() { PropertyToBeWatched = "2" });
            MyList.Add(new CustomClass() { PropertyToBeWatched = "2" });

            SelectedItem = MyList[1]; //Here is where it happens
        }

    }

通过将ComboBox的SelectedItem绑定到实体,我们可以实现您想要的效果。这适用于TwoWay ofcourse。

希望这会有所帮助。 :d