2016-02-23 3 views
0

У меня есть простая привязка элементов к списку объектов Записи. Кнопка обновляет LastUpdated каждого элемента в Списке. Как мне изменить событие с изменением свойства, чтобы поле LastUpdated обновлялось в ItemsControl. Я упростил свой пример, чтобы выяснить проблему привязки. В моей реальной выборке используются PRISM и сторонние элементы управления.Обновить привязки в itemscontrol wpf

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> 
+0

Вы добавляете новые элементы динамически где-нибудь? – kskyriacou

+0

Как насчет 'ItemsControl i; i.Items.Refresh(); ' – Sakura

+0

Элементы не добавляются динамически. Изменяется только состояние свойства LastUpdated. Что происходит, так это то, что когда я увеличиваю событие изменения свойства для этого конкретного свойства, которое изменилось, привязка происходит только один раз, а не для всех элементов в ItemsSource в моем примере. Есть ли специальный способ повысить событие с измененной стоимостью для элементов в списке? – TrustyCoder

ответ

1

Вы должны проверить 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

Тогда вы должны переписать ваш 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.

1

Я думаю, что вы должны вариантов здесь:

  1. Создать метод, как это:

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

Тогда, когда вы хотите обновить ap roperty вы идете:

OnPropertyChanged("TheNameOfTheProperty"); 

или если вы хотите обновить каждые свойства в классе:

OnPropertyChanged(string.Empty); 

Если вы не уверены, какое свойство обновлять, когда я рекомендую вам пойти с последним.

  1. Вы можете, но я рекомендую вам не делать этого так: создать новый список, добавить обновленные значения, очистить исходный список, установить исходный список в новый список а затем обновить имя свойства списка.
1

Вы не привязываетесь к UpdateCmd и вызываете обновление в любом месте, если оно не находится в обработчике Click, но для этого вы должны использовать подход MVVM.

Изменить обработчик события нажатия на команду связывания с вашего ViewModel в XAML как так

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

Затем в конструктор привязки модели представления создают новый RelayCommand или что-либо класс реализации ICommand походит так, где contructor принимает делегата действия.

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")); 
    } 
} 

Но вы должны действительно просто реализовать INotifyPropertyChanged на модели входа, а также и поднять мероприятие на сеттеры собственности, привязки будут обновляться без уведомления о том, что вся коллекция должна обновляться.

Смежные вопросы