Как связать и автоматически обновить список wpf

Здесь несколько вопросов

Первый

Это моя реализация, но она не работает, как я могу заставить ее работать?

<grid> // xaml part
 </grid><button content="Start Crawling Root Sites - This Deletes All Data" horizontalalignment="Left" margin="10,10,0,0" verticalalignment="Top" command="{Binding StartCrawling}" click="click_start_Crawling"><code>
 <listbox name="lstBoxEvents" horizontalalignment="Left" margin="294,10,0,0" verticalalignment="Top">
 <listbox.itemtemplate>
 <datatemplate>
 <grid margin="1">
 <grid.columndefinitions>
 <columndefinition>
 </columndefinition></grid.columndefinitions>
 <textblock grid.column="1" text="{Binding ocEvents}">
 </textblock></grid>
 </datatemplate>
 </listbox.itemtemplate>
 </listbox>



 private void click_start_Crawling(object sender, RoutedEventArgs e) // inside mainwindow
 {
 PublicStaticFunctions.AddMsgToEvents("trial");
 }

 public static class PublicStaticFunctions // seperate class
{
 public static ObservableCollection<string> ocEvents = new ObservableCollection<string>();

 public static void AddMsgToEvents(string srMessage)
 {
 ocEvents.Insert(0, srMessage);
 }
}
</string></string></code> <p> Мой второй вопрос при запуске многопоточного, если несколько потоков доступа к функции AddMsgToEvents и добавляет переменную, будет ли все-таки автоматически обновлять список без каких-либо проблем?</p> <p> большое спасибо</p> </button>
1 ответ

Эта строка:

public static ObservableCollection<string> ocEvents = new ObservableCollection<string>();
</string></string>

Это не свойство Dependency, а свойство, реализующее INotifyPropertyChanged, оно также является статичным, если вы используете viewmodel, вы можете сделать это так, как описано ниже, ну, вы можете использовать код, но он вызывает двойное перерисовку. В любом случае вам нужно изменить его на DP или пропеллер, как показано ниже:

private ObservableCollection<string> ocEvents = new ObservableCollection<string>();
public ObservableCollection<string> OcEvents
{
 get { return ocEvents; }
 set
 {
 if (Equals(value, ocEvents)) return;
 ocEvents = value;
 OnPropertyChanged();
 }
}
public event PropertyChangedEventHandler PropertyChanged;

[NotifyPropertyChangedInvocator] // Comment out if you don't have R#
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
 PropertyChangedEventHandler handler = PropertyChanged;
 if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
</string></string></string>

Привязка к статическому классу/свойству имеет некоторые странности, вы должны связываться по-разному. Я сейчас ухожу, поэтому я не могу предоставить и пример. В приведенном выше случае я бы создал vm и службу для получения моего события вместо того, чтобы сделать мой vm unittestable (создать интерфейс службы, предоставляющей события, и иметь свойство события на vm).

AddMsgToEvents() Должен быть вызван в поток диспетчера. Плохой взлом - это добавить следующий код. Назовите его

BeginInvoke(YourMethod);

Добавьте код в свой базовый класс vm, я знаю, что диспетчер должен быть "использован" таким образом, но для упрощения.

public void BeginInvoke(Action action)
 {
 if( Application.Current.Dispatcher.CheckAccess()) 
 Application.Current.Dispatcher.BeginInvoke(action);
 else
 {
 action();
 }
 }

 public void Invoke(Action action)
 {
 if (Application.Current.Dispatcher.CheckAccess())
 Application.Current.Dispatcher.BeginInvoke(action);
 else
 {
 action();
 }
 }


public static class PublicStaticFunctions

У вас есть свое обслуживание прямо там, просто нестатический и создайте его интерфейс: D Переместите свою опору в vm/codebehind или вам понадобятся некоторые изменения в вашем привязке к ней, pluss hava Prop или DP. короткий ответ.

Изменение: пример сервиса

public interface IEventService
{
 ObservableCollection<string> GetEvents();
 void AddEvent(String eventToAdd);
}

public class EventService : IEventService
{
 private readonly ObservableCollection<string> events;

 public EventService(ObservableCollection<string> events)
 {
 this.events = events;
 }

 public EventService()
 {
 events = new ObservableCollection<string>();
 }

 public ObservableCollection<string> Events
 {
 get { return events; }
 //set { events = value; }
 }

 public ObservableCollection<string> GetEvents()
 {
 return events;
 }

 public void AddEvent(String eventToAdd)
 {
 events.Add(eventToAdd);
 }
}
</string></string></string></string></string></string>

Подайте этот интерфейс на ваш vm ctor (TDD :)) или codebehind ctor. Выделите и сохраните его в кокаине IOC, servicelocator или любом другом.

Надеюсь, поможет,

Ура,

Stian

licensed under cc by-sa 3.0 with attribution.