簡體   English   中英

刷新ItemsControl WPF中的綁定

[英]refresh bindings in itemscontrol wpf

我有一個簡單的項控件綁定到條目對象列表。 該按鈕更新列表中每個項目的LastUpdated。 如何引發屬性更改事件,以便在ItemsControl中更新LastUpdated字段。 我簡化了我的示例,只是為了弄清綁定問題。 我的真實樣本使用PRISM和第三方控件。

C#代碼:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Input;

namespace TestItemsControl
{
    public class Entry
    {
        public string Name { get; set; }

        public DateTime LastUpdated { get; set; }
    }
}

namespace TestItemsControl
{
    public class TestViewModel: INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        public List<Entry> Entries { get; set; }

        public ICommand UpdateCmd { get; set; }

        public TestViewModel()
        {
            this.Entries = new List<Entry>();
            this.Entries.Add(new Entry{ Name = "1", LastUpdated = DateTime.Now });
            this.Entries.Add(new Entry { Name = "2", LastUpdated = DateTime.Now });
            this.Entries.Add(new Entry { Name = "3", LastUpdated = DateTime.Now });
        }

        public void Refresh()
        {
            if (this.PropertyChanged!= null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs("Entries"));
            }
        }
    }
}

XAML:

<Application x:Class="TestItemsControl.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:TestItemsControl"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
        <local:TestViewModel x:Key="viewModel"/>
    </Application.Resources>
</Application>


<Window x:Class="TestItemsControl.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:TestItemsControl"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525" DataContext="{StaticResource viewModel}">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <ItemsControl Grid.Row="0" ItemsSource="{Binding Entries}">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <StackPanel Orientation="Vertical"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Grid>
                        <TextBlock Text="{Binding Name}"/>
                        <TextBlock Text="{Binding LastUpdated}"/>
                    </Grid>
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
        <Button Grid.Row="1" Content="Update" Click="Button_Click"/>
    </Grid>
</Window>

然后,您必須重寫Entry

public class Entry: INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public string Name { get; set; }

    DateTime lastUD;
    public DateTime LastUpdated
    {
        get
        {
            return lastUD;
        }
        set
        {
            lastUD = value;
            if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs("LastUpdated"));
        }
    }
}

另外,將List<Entry>更改為ObservableCollection<Entry>

namespace TestItemsControl
{
    public class TestViewModel
    {
        public ObservableCollection<Entry> Entries=new ObservableCollection<Entry>();

        public ICommand UpdateCmd { get; set; }

        public TestViewModel()
        {
            this.Entries.Add(new Entry{ Name = "1", LastUpdated = DateTime.Now });
            this.Entries.Add(new Entry { Name = "2", LastUpdated = DateTime.Now });
            this.Entries.Add(new Entry { Name = "3", LastUpdated = DateTime.Now });
        }
    }
}

這樣,您不必調用Refesh函數。

如果沒有人訂閱活動,則必須檢查Null

public class Entry : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    public string Name { get; set; }

    DateTime lastUD;
    public DateTime LastUpdated
    {
        get
        {
            return lastUD;
        }
        set
        {
            lastUD = value;
            if(PropertyChanged != NULL)
               PropertyChanged(this, new PropertyChangedEventArgs("LastUpdated"));
        }
    }
}

我認為您必須在這里選擇:

  1. 創建這樣的方法:

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

然后,每當您要更新屬性時,都可以:

OnPropertyChanged("TheNameOfTheProperty");

或者如果您想更新該類中的每個屬性:

OnPropertyChanged(string.Empty);

如果不確定何時更新哪個屬性,建議您選擇后者。

  1. 您可以,但是我建議您不要這樣:實例化一個新列表,添加更新的值,清除原始列表,將原始列表設置為新列表,然后更新列表的屬性名稱。

您沒有綁定UpdateCmd並在任何地方調用Refresh,除非它在Click處理程序中,但是您應該使用MVVM方法來執行此操作。

將Click事件處理程序更改為來自xaml中的viewmodel的命令綁定,如下所示

<Button Grid.Row="1" Content="Update" Command={Binding UpdateCmd}/>

然后在視圖模型的構造函數綁定中,創建一個新的RelayCommand或ICommand實現類的樣子,以便構造器接收動作委托。

this.UpdateCmd  = new RelayCommand(this.Update);

另外,您可能應該將“刷新”更改為“更新”,以更新條目的時間戳。

public void Update()
{
    foreach (var entry in this.Entries)
    {
        entry.LastUpdated = DateTime.Now;
    }

    if (this.PropertyChanged!= null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs("Entries"));
    }
}

但實際上,您也應該僅在Entry模型上實現INotifyPropertyChanged並在屬性設置器上引發事件,綁定將被更新,而不會通知整個集合應被更新。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM