列表框未由依赖项属性observablecollection更新

时间:2012-01-05 20:27:24

标签: c# windows-phone-7

我正在处理的功能是关键字搜索的自动完成功能。一旦用户在搜索栏中输入内容,视图模型就会使用关键字参数调用自动完成API,以获取自动完成建议并将其放入observablecollection容器中。这个observablecollection是一个依赖属性,它与列表框绑定以显示自动完成建议。我的问题是依赖属性正确填充但列表框不显示任何内容。以下是一些代码:

xaml.cs中的数据绑定:

protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            searchBar.Focus();
            _searchViewModel = new SearchViewModel();
            DataContext = _searchViewModel;
        }

调用视图模型中的方法来调用自动完成API:

private void searchBar_TextChanged(object sender, TextChangedEventArgs e)
        {
            _searchViewModel.getTypeaheadListFromServer(searchBar.Text);
        }

视图模型中的依赖属性,它已成功填充:

public ObservableCollection<TypeaheadElement> TypeaheadList
        {
            get { return (ObservableCollection<TypeaheadElement>)GetValue(TypeaheadListProperty); }
            set { SetValue(TypeaheadListProperty, value); }
        }

        // Using a DependencyProperty as the backing store for TypeaheadList.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TypeaheadListProperty =
            DependencyProperty.Register("TypeaheadList", typeof(ObservableCollection<TypeaheadElement>), typeof(SearchViewModel), new PropertyMetadata(null));

xaml中的数据绑定:

<ListBox Name="typeahead" Grid.Row="1" ItemsSource="{Binding TypeaheadList}" Height="518" Margin="0,0,0,-518" SelectionChanged="typeahead_SelectionChanged">
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <TextBlock TextWrapping="Wrap" Text="{Binding TypeaheadElementStr}" FontSize="{StaticResource ListItemFontSize}" FontFamily="Segoe WP" Margin="10,0,0,0" VerticalAlignment="Top">
                                         <TextBlock.Foreground>
                                                 <SolidColorBrush Color="{StaticResource ListItemFontColor}"/>
                                         </TextBlock.Foreground>
                                </TextBlock>
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                    </ListBox>

非常感谢你的帮助!

3 个答案:

答案 0 :(得分:0)

试试这个

<ListBox Name="typeahead" Grid.Row="1" ItemsSource="{Binding TypeaheadList, UpdateSourceTrigger=PropertyChanged}" Height="518" Margin="0,0,0,-518" SelectionChanged="typeahead_SelectionChanged">

答案 1 :(得分:0)

我不明白为什么你试图实现DependencyProperty就是这种情况。 TypeaheadListBinding的来源,而不是目标,对吧?因此,它可以是ViewModel上的简单属性。

答案 2 :(得分:0)

您是否尝试过使用工具包中的AutoCompleteBox?如果可能性列表不大,则可以预先填充AutoCompleteBox的ItemsSource。如果您无法预填充它,您可以向服务器发出异步请求,以便在应用启动时获得所有可能性。 以下是一些关于使用AutoCompleteBox的博客: http://www.jeff.wilcox.name/2011/03/acb-in-pivot/

如果无法做到,那么您可以执行以下操作:

的Xaml:

    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
        <toolkit:AutoCompleteBox ItemsSource="{Binding People}" Populating="AutoCompleteBox_Populating" />
    </Grid>

代码:

public partial class MainPage : PhoneApplicationPage
{
    // Constructor
    public MainPage()
    {
        People = new ObservableCollection<string> {"Shawn", "steve", "Bob", "randy", "mike"};
        DataContext = this;
        InitializeComponent();
    }

    public ObservableCollection<string> People { get; set; }

    private void AutoCompleteBox_Populating(object sender, PopulatingEventArgs e)
    {
        // Have we already populated with this text?
        if(People.Any(person => person.ToLower().StartsWith(e.Parameter.ToLower()))) return;

        Completer c = new Completer();
        c.Completed += new EventHandler<EventArgs>(c_Completed);
        c.Complete(e.Parameter);
    }

    void c_Completed(object sender, EventArgs e)
    {
        Completer c = sender as Completer;
        foreach (var name in c.Names)
        {
            People.Add(name);       
        }
    }
}

internal class Completer
{
    public event EventHandler<EventArgs> Completed;

    public IEnumerable<string> Names { get; set; }

    public void Complete(string parameter)
    {
        if (parameter.StartsWith("d"))
        {
            Names = new List<string>() { "Dick", "Dave" };
        }
        else if (parameter.StartsWith("j"))
        {
            Names = new List<string>() { "Jane", "Joe" };
        }
        OnCompleted();
    }

    protected virtual void OnCompleted()
    {
        var handler = Completed;
        if (handler != null) handler(this, EventArgs.Empty);
    }
}