2016-01-16 187 views
1

我正在使用搜索窗口將搜索結果加載到ObservableCollection中,然後使用ListView顯示結果。當綁定的ObservableCollection發生變化時,ListView不會更新

搜索完成後,將ListView的ItemSource設置爲ObservableCollection可以正確填充列表。

我試圖讓ListView更新爲搜索添加額外的結果,但ListView沒有填充任何數據。我無法弄清楚我的約束力正在下降。

我的研究表明使用DataContext的各種方式,儘管似乎沒有幫助;我試着將它分配給「this」和使用CodeBehind以及xaml Window級別的CachedData類。

對不起,我留下了一些我認爲可能有助於增加問題背景的代碼片段。

XAML:

<Window x:Class="SLX_Interface.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:local="clr-namespace:SLX_Interface" 
    mc:Ignorable="d" 
    Title="SLX Search" Height="auto" Width="auto"> 
<Window.CommandBindings> 
</Window.CommandBindings> 
<Grid> 
    <Grid.Resources> 
     <local:CachedData x:Key="cachedData" /> 
    </Grid.Resources> 
    <TabControl x:Name="tabControl" Grid.RowSpan="2" Margin="0,20,0,0"> 
     <TabItem Header="Accounts" Name="accountsTab"> 
      <Grid> 
       <ListView x:Name="accountSearchResultsListView" Margin="5,32,5,30" DataContext="staticResource cachedData" ItemsSource="{Binding Path=accounts}" IsSynchronizedWithCurrentItem="True"> 
        <ListView.View> 
         <GridView x:Name="accountSearchResultsGridView"> 
          <GridViewColumn Header="SData Key" DisplayMemberBinding="{Binding SDataKey}"/> 
          <GridViewColumn Header="Account Name" DisplayMemberBinding="{Binding AccountName}"/> 
         </GridView> 
        </ListView.View> 
       </ListView> 
      </Grid> 
     </TabItem> 
    </TabControl> 
</Grid> 

代碼隱藏從MainWindow.xaml.cs內:

private async void SearchAccount(string searchTerm, string searchField, string searchOperator) 
    { 
     //Create the string we'll use for searching 
     string urlString = "Stuff"; 

     //Create an ObservableCollection, then use it to blank the cache 
     ObservableCollection<Account> resultsList = new ObservableCollection<Account>(); 
     CachedData.accounts = resultsList; 

     //Getting data from the search using an XML Reader 
     XmlReader resultsReader = null; 

     try 
     { 
      //Using XmlReader to grab the search results from SLX 
      XmlUrlResolver resultsResolver = new XmlUrlResolver(); 
      resultsResolver.Credentials = LoginCredentials.userCred; 

      XmlReaderSettings resultsReaderSettings = new XmlReaderSettings(); 
      resultsReaderSettings.XmlResolver = resultsResolver; 
      resultsReaderSettings.Async = true; 

      resultsReader = XmlReader.Create(urlString, resultsReaderSettings); 
     } 
     catch (Exception error) 
     { 

     } 

     //Grabbing data from the XML and storing it, hopefully updating the ListView as we go 
     using (resultsReader) 
     { 
      while (await resultsReader.ReadAsync()) 
      { 
       while (resultsReader.ReadToFollowing("slx:Account")) 
       { 
        //Setting data from the XML to a new Account object ready to be passed to the list 
        Account account = new Account(); 
        account.GUID = new Guid(); 

        resultsReader.MoveToFirstAttribute(); account.SDataKey = resultsReader.Value; 
        resultsReader.ReadToFollowing("slx:AccountName"); account.AccountName = resultsReader.ReadElementContentAsString(); 

        CachedData.accounts.Add(account); 

        //--Uncommenting this gives odd results; 
        //--The first item is displayed, any others aren't. 
        //--If there are a lot of items, the application eventually errors like mad and ends. 
        //--Looks like one error window for each item, though I don't see the message before they die along with the application. 
        //accountSearchResultsListView.ItemsSource = CachedData.accounts; 
       } 
      } 
     } 

     //--Uncommenting this works but shows the data once the entire XML has been read through, which can take some time so isn't ideal. 
     //accountSearchResultsListView.ItemsSource = CachedData.accounts;  } 

類的引用的上方,存儲在單獨的.cs文件,但在相同的命名空間:

public class CachedData 
{ 
    public static ObservableCollection<Account> accounts { get; set; } 

    public static event PropertyChangedEventHandler PropertyChanged; 

    public static event EventHandler<PropertyChangedEventArgs> StaticPropertyChanged = delegate { }; 
    private static void NotifyStaticPropertyChanged(string propertyName) 
    { 
     StaticPropertyChanged(null, new PropertyChangedEventArgs(propertyName)); 
    } 
} 

public class Account : IEquatable<Account> 
{ 
    public Guid GUID { get; set; } 
    public string SDataKey { get; set; } 
    public string AccountName { get; set; } 

    public override string ToString() 
    { 
     return AccountName; 
    } 

    public override bool Equals(object obj) 
    { 
     if (obj == null) return false; 
     Account objAsPart = obj as Account; 
     if (objAsPart == null) return false; 
     else return Equals(objAsPart); 
    } 

    public override int GetHashCode() 
    { 
     return 0; 
    } 

    public bool Equals(Account other) 
    { 
     if (other == null) return false; 
     return (GUID.Equals(other.GUID)); 
    } 
} 

我很感激你可以提供的任何幫助,這讓我難倒了好幾天。

回答

1

當您在xaml中設置數據綁定時,綁定應用程序啓動時存在的ObservableCollection實例。所以請在應用程序啓動之前實例化一個實例,並且不要將其替換爲新實例,除非您在代碼後面重置數據綁定。如果您需要清除其元素,請使用Clear方法。

+0

這樣做,我刪除了「重置」,它工作正常。現在使用.Clear函數重設列表。 由於沒有實例化對象,我確實得到了對象引用錯誤,通過遵循這裏的答案解決了這個問題:http:// stackoverflow。com/questions/15895763/get-object-reference-not-set-to-an-an-instance-of-object-error-from-static-membe 感謝您的幫助! – Mannheimd

1

問題是你正在使用的ObservableCollection它實現INotifyCollectionChanged內部。這不會引起收藏的每一個變化。只有當某個項目被添加到集合中或刪除了時,它纔會引起集合更改。

因此,如果有人指定一個新的收集實例(作爲您的案例)會發生什麼情況。因此重新設置綁定並不是很好的選擇,您可以自己提出更改。通過簡單地執行INotifyPropertyChanged的。(通常情況下)

public class DataClass : INotifyPropertyChanged 
{ 

    public event PropertyChangedEventHandler PropertyChanged; 

    public void OnPropertyChanged(string propertyName) 
    { 
     if (PropertyChanged != null) 
     { 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 


    private ObservableCollection<string> collection; 

    public ObservableCollection<string> Collection 
    { 
     get { return collection; } 
     set 
     { 
      collection = value; 
      OnPropertyChanged("Collection"); 
     } 
    }  
} 

所以分配集合空或一個新的實例也將得到反映到綁定控件。 (你已經有NotifyStaticPropertyChanged你只需要創建一個完整的屬性,只是在需要時提出更改。)

相關問題