【问题标题】:DataContext - ListView - Refresh UI - INotifyPropertyChangedDataContext - ListView - 刷新 UI - INotifyPropertyChanged
【发布时间】:2013-08-13 15:39:17
【问题描述】:

在 Windows 商店应用程序上工作时,我尝试在更新某些数据时更新/刷新 listView。但是,尽管我阅读了所有示例和文档,但它不起作用......

下面是我的代码: (我不提供我的 xaml 文件,它只是一个示例 listView)。

那么实现INotifyPropertyChanged接口的类:

public class Download : INotifyPropertyChanged
    {
        public enum DownloadState
        {
            Running,
            Waiting,
            Pausing,
            Paused,
            Cancelling,
            Cancelled
        };

        private String Uri;
        private StorageFile storageFile;
        private String tempFileName;



        private String fileName;
        private String version ;

        private long totalSize ;
        private long downloadedBytes;

        private DownloadState state;
        private Protocol protocol;


        public Download(String Uri, StorageFile file, String fileName, String version, long totalSize, Protocol protocol)
        {
            this.Uri = Uri;
            this.storageFile = file;
            this.tempFileName = "";
            this.fileName = fileName;
            this.version = version;

            this.totalSize = totalSize;
            this.downloadedBytes = 0;

            this.state = DownloadState.Waiting;

            this.protocol = protocol;


        }


        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
        {
            System.Diagnostics.Debug.WriteLine("Update!"); //ok
            if (PropertyChanged != null)
            {
                //PropertyChanged is always null and shouldn't.
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
           public DownloadState State
        {
            get{return this.state;}
            set { 
                this.state = value;
                NotifyPropertyChanged();
            }
        }

        //+some others methods

    }
}

还有地铁应用的主页:

// The Basic Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234237

namespace ClientAirNavLight_WS
{
    /// <summary>
    /// A basic page that provides characteristics common to most applications.
    /// </summary>
    public sealed partial class MainPage : ClientAirNavLight_WS.Common.LayoutAwarePage
    {
        /// <summary>
        /// Represent a Web Service proxy.
        /// </summary>
        private AirNavLight_WSClientClient proxyWS;

        /// <summary>
        /// Initiialize the component of the application's main page.
        /// </summary>
        public MainPage()
        {
            this.InitializeComponent();          

        }



        /// <summary>
        /// Populates the page with content passed during navigation.  Any saved state is also
        /// provided when recreating a page from a prior session.
        /// </summary>
        /// <param name="navigationParameter">The parameter value passed to
        /// <see cref="Frame.Navigate(Type, Object)"/> when this page was initially requested.
        /// </param>
        /// <param name="pageState">A dictionary of state preserved by this page during an earlier
        /// session.  This will be null the first time a page is visited.</param>
        protected override void LoadState(Object navigationParameter, Dictionary<String, Object> pageState)
        {
        }

        /// <summary>
        /// Preserves state associated with this page in case the application is suspended or the
        /// page is discarded from the navigation cache.  Values must conform to the serialization
        /// requirements of <see cref="SuspensionManager.SessionState"/>.
        /// </summary>
        /// <param name="pageState">An empty dictionary to be populated with serializable state.</param>
        protected override void SaveState(Dictionary<String, Object> pageState)
        {
        }


        //Simulate data update.
        private async void Button_Click(object sender, RoutedEventArgs e)
        {

            object selected = this.ListResult.SelectedItem;
            if (selected != null)
            {
                //simulate an update in data.
                // ListView should be refresh in order to reflect changes made here.
                Download dl = (Download)selected;
                if (dl.State == Download.DownloadState.Paused)
                {
                    dl.State = Download.DownloadState.Running;
                }
                else
                {
                    dl.State = Download.DownloadState.Paused;
                }

            }
            else
            {
                //Just add an item to the list view.
                StorageFile file = await this.getStorageFile("test");
                Download dl = new Download("192.128.2.14", file, "test", "1.2", 100, Protocol.HTTP);
                this.ListResult.Items.Add(dl);


                this.ListResult.DataContext = dl;// Does not work.


            }
        }


        private async Task<StorageFile> getStorageFile(String suggestedFileName)
        {
            FileSavePicker savePicker = new FileSavePicker();
            savePicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
            // Dropdown of file types the user can save the file as
            savePicker.FileTypeChoices.Add("Application/pdf", new List<string>() { ".pdf" });
            savePicker.FileTypeChoices.Add("Archive", new List<string>() { ".zip", ".rar", ".7z" });
            savePicker.FileTypeChoices.Add("Plain-text", new List<string>() { ".txt" });
            // Default file name if the user does not type one in or select a file to replace
            savePicker.SuggestedFileName = suggestedFileName;
            return await savePicker.PickSaveFileAsync();
        }


    }
}

那么我应该如何使用 listView.DataContext?我是否误解了如何使用 INotifyPropertyChanged?

编辑:

我的 listView 是如何定义的:

 <ListView x:Name="ListResult" HorizontalAlignment="Left" Height="200" Margin="10,56,0,0" VerticalAlignment="Top" Width="653" SelectionMode="Single"/>

【问题讨论】:

    标签: c# .net windows-store-apps datacontext


    【解决方案1】:

    你为什么要设置this.ListResult.DataContext = dl?在处理 ListView 时,ItemsSource 是所有被迭代的对象的集合,而不是 DataContext。此外,ItemsSource 应该是一个集合而不是一个项目。因此,如果您要绑定到某个属性,则该属性应该作为 ItemsSource 集合中的项目属性存在。

    但是,您似乎没有集合,因此您使用this.ListResult.Items.Add(dl) 将 dl 直接添加到 ListView。这种方法应该有效,但是取出 this.ListResult.DataContext = dl 或将 this.ListResult.ItemsSource 设置为集合并将 dl 添加到该集合

    我不熟悉 [CallerMemberName],但如果您遇到 propertyName 为空的问题,请尝试以下操作

        public DownloadState State
        {
            get{return this.state;}
            set {
                if( this.state != value )
                {
                    this.state = value;
                    NotifyPropertyChanged("State");
                }
            }
        }
    

    此外,您要绑定的所有属性都应该是公共的并调用 NotifyPropertyChanged,如下所示

        private long totalSize ;
    
        public long TotalSize
        {
            get{return this.totalSize;}
            set {
                if( this.totalSize != value )
                {
                    this.totalSize = value;
                    NotifyPropertyChanged("TotalSize");
                }
            }
        }
    

    【讨论】:

    • 谢谢,但是当我将this.ListResult.ItemsSource 设置为集合并将dl 添加到该集合时,只有在我将this.ListResult.ItemsSource 设置为此集合之前将项目添加到集合时,才会显示集合的内容.然后,问题还是一样:在我的课堂上下载方法NotifyPropertyChanged 是在我更改状态时调用,但PropertyChanged 始终为空(是否使用集合)。
    • @Francois,如果您将数据绑定到集合,则 NotifyPropertyChanged 仅在您更改整个集合时触发。当您从集合中添加或删除项目时,它不会触发。
    • @Francois,我认为你误解了。 davron12 概述了如何使用INotifyPropertyChanged 以及进行数据绑定的正确方法。但是,除非您更改整个集合,否则您的 UI 不会更新。如果您只是将项目添加到集合中,则 UI 不会更新。
    • 您分配给this.ListResult.ItemsSource 的集合类型是什么?使用ObservableCollection&lt;Download&gt;,因为它会在添加和删除项目时触发事件,而常规Collection 不会。 NotifyPropertyChanged 不会在将项目添加到集合时触发,而只会在属性本身更改值时触发。
    • 如果您使用ObservableCollection,并且您正在添加实现INotifyPropertyChangedDownload,您应该已经准备就绪。可观察集合通知您的 ListView 项目已添加/删除,Download 通知 ListView 其属性已更改,您无需执行与您在代码中已经执行的操作不同的任何操作。
    【解决方案2】:

    在您的 Download 类中,唯一会在 UI 中更新的 Property 是 State,因为它有一个 getter 和 setter。

    如果没有您的 XAML,就无法看到您尝试显示的内容,但通常情况下,您会将 DataContext 对象(在本例中为 dl)的属性绑定到数据模板中的不同控件,然后列表视图可以显示这些控件。

    但是这些属性需要是公共的,并且有 INotifyPropertyChanged 的​​ getter 和 setter 来更新这些属性绑定到的 UI。

    例如,如果您希望文件名显示在 ListView 中,则至少需要像这样声明文件名属性:

    public String fileName {get; set; }
    

    【讨论】:

    • 我不在列表视图中使用数据模板。 listview 使用默认的 toString 方法来显示不同的对象。在类 Download 中,当我更改状态时调用方法 NotifyPropertyChangedPropertyChanged 始终为空。
    • 这真的对我有用,我在这个问题上坚持了 2 天,现在它通过简单的 getter 和 setter 解决了,谢谢 Stewbob
    【解决方案3】:

    Zangdak -- 解决该问题的一种方法是每次集合中的项目发生更改时,只需将 ListView 的 ItemSource 设置为 null,然后将其设置回您的集合。如果您这样做,UI 将会更新,您会看到新项目已添加到您的收藏中。

    佩奇阿克

    【讨论】:

      猜你喜欢
      • 2023-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-31
      • 2019-04-22
      • 2016-07-30
      • 1970-01-01
      相关资源
      最近更新 更多