2017-07-28 75 views
1

我一直在試圖創建一個用戶控件,使用這個article作爲我的開始。 我的最終結果是提供一個集合並使用TextBox來過濾集合,並在ListView中顯示過濾結果。UserControl不會顯示綁定的集合

問題是,我的綁定似乎無法正常工作。該集合沒有傳遞給UserControl。請記住,這是我第一次創建UserControl。爲什麼會發生?

SearchList.Xaml

<UserControl x:Class="CreatingControls.SearchList" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:local="clr-namespace:CreatingControls" 
     mc:Ignorable="d" 
     d:DesignHeight="300" d:DesignWidth="300" Loaded="SearchList_OnLoaded"> 


<StackPanel> 
    <TextBox Name="txtFilter" 
      TextChanged="txtFilter_TextChanged" 
      Margin="5" FontSize="20" /> 

    <TextBox IsEnabled="False" Text="Search:" 
      FontSize="16" BorderThickness="0" /> 

    <ListView Name="listView" 
       SelectedValue="{Binding Path=SelectedItem}" 
       DisplayMemberPath="Value" 
       BorderBrush="LightGray" Margin="5" /> 
</StackPanel> 

SearchList.xaml.cs

public partial class SearchList : UserControl 
{ 
    #region AllItems 

    public List<Collection> AllItems 
    { 
     get { return (List<Collection>)GetValue(AllItemsProperty); } 
     set { SetValue(AllItemsProperty, value); } 
    } 

    public static readonly DependencyProperty AllItemsProperty = 
     DependencyProperty.Register("AllItems", typeof(List<Collection>), 
      typeof(SearchList), new PropertyMetadata(default(List<Collection>))); 

    #endregion 

    #region SelectedItem 

    public Collection SelectedItem 
    { 
     get { return (Collection)GetValue(SelectedItemProperty); } 
     set { SetValue(SelectedItemProperty, value); } 
    } 

    public static readonly DependencyProperty SelectedItemProperty = 
     DependencyProperty.Register("SelectedItem", typeof(Collection), 
      typeof(SearchList), new PropertyMetadata(default(Collection))); 

    #endregion 

    public SearchList() 
    { 
     InitializeComponent(); 

     listView.ItemsSource = AllItems; 

     if (listView.ItemsSource != null) 
     { 
      CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(listView.ItemsSource); 
      view.Filter = ItemsFilter; 
     } 
    } 

    private void SearchList_OnLoaded(object sender, RoutedEventArgs e) 
    { 
     if (listView.ItemsSource == null) 
      return; 

     CollectionViewSource.GetDefaultView(listView.ItemsSource).Filter = ItemsFilter; 
    } 

    private void txtFilter_TextChanged(object sender, TextChangedEventArgs e) 
    { 
     if (listView.ItemsSource == null) 
      return; 

     CollectionViewSource.GetDefaultView(listView.ItemsSource).Refresh(); 
    } 

    private bool ItemsFilter(object item) 
    { 
     if (listView.ItemsSource == null) 
      return false; 

     if (String.IsNullOrEmpty(txtFilter.Text)) 
      return true; 

     var collectionItem = (Collection)item; 

     return (collectionItem.Value.StartsWith(txtFilter.Text, StringComparison.OrdinalIgnoreCase) || collectionItem.Value.StartsWith(txtFilter.Text, StringComparison.OrdinalIgnoreCase)); 
    } 

} 

Collection.cs

public class Collection : INotifyPropertyChanged 
{ 
    private string _id; 
    public string Id 
    { 
     get { return _id; } 
     set { SetField(ref _id, value, "Id"); } 
    } 

    private string _value; 
    public string Value 
    { 
     get { return _value; } 
     set { SetField(ref _value, value, "Value"); } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
    protected virtual void OnPropertyChanged(string propertyName) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); 
    } 
    protected bool SetField<T>(ref T field, T value, string propertyName) 
    { 
     if (EqualityComparer<T>.Default.Equals(field, value)) return false; 
     field = value; 
     OnPropertyChanged(propertyName); 
     return true; 
    } 
} 

MainWindow.xaml(窗口調用創建的用戶控件)

<Window x:Class="CreatingControls.MainWindow" 
    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:uControls="clr-namespace:CreatingControls" 
    mc:Ignorable="d" 
    d:DataContext="Models." 
    Title="MainWindow" > 

<Grid> 
    <uControls:SearchList x:Name="slist" /> 
</Grid> 

MainWindow.xaml.cs

public partial class MainWindow : Window 
{ 
    public static List<Collection> items { get; set; } 
    public User SelectedUser { get; set; } 

    public MainWindow() 
    { 
     InitializeComponent(); 

     items = new List<Collection>(); 
     items.Add(new Collection { Id = "1", Value = "A" }); 
     items.Add(new Collection { Id = "2", Value = "B" }); 
     items.Add(new Collection { Id = "3", Value = "C" }); 
     items.Add(new Collection { Id = "4", Value = "D" }); 
     items.Add(new Collection { Id = "5", Value = "E" }); 
     items.Add(new Collection { Id = "6", Value = "F" }); 
     items.Add(new Collection { Id = "7", Value = "G" }); 
     items.Add(new Collection { Id = "8", Value = "H" }); 

     slist.AllItems = items; 
    } 
} 

回答

2

您在SearchList構造分配

listView.ItemsSource = AllItems; 

。後來,在主窗口的構造函數,你做

slist.AllItems = items; 

現在,你似乎是的印象是listView.ItemsSource奇蹟般地保存到items收集你的主窗口的參考下。事實並非如此。

而不是直接分配,使用數據綁定。在SearchList XAML,這樣寫:

<ListView ItemsSource="{Binding AllItems, 
         RelativeSource={RelativeSource AncestorType=UserControl}}" .../> 

,並從SearchList構造函數刪除listView.ItemsSource = AllItems