Вы можете сделать это, используя прикрепленное поведение, чтобы привязать обработчик к событию, которое запускается в модели представления. Вы не можете связываться непосредственно с событиями, хотя, так что вы должны обернуть их в классе, как так:
public class Refresher
{
public delegate void RefreshDelegate();
public event RefreshDelegate Refresh;
public void DoRefresh()
{
if (this.Refresh != null)
this.Refresh();
}
}
Теперь добавьте экземпляр, что в вашей модели представления:
public class MyViewModel
{
public IList<string> Items { get; set; }
private Refresher _Refresher = new Refresher();
public Refresher Refresher {get {return this._Refresher;}}
}
Далее создайте приложенный поведение, которое регистрирует экземпляр делегата с этим событием и заставляет ListBox, чтобы обновить его связывания:
public static class RefreshBehavior
{
public static readonly DependencyProperty RefresherProperty = DependencyProperty.RegisterAttached(
"Refresher",
typeof(Refresher),
typeof(RefreshBehavior),
new PropertyMetadata(null, OnRefresherChange));
public static void SetRefresher(DependencyObject source, Refresher value)
{
source.SetValue(RefresherProperty, value);
}
public static Refresher GetRefresher(DependencyObject source)
{
return (Refresher)source.GetValue(RefresherProperty);
}
private static void OnRefresherChange(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Refresher.RefreshDelegate handler =() =>
{
var listBox = d as ListBox;
listBox.Items.Refresh();
};
if (e.NewValue != null)
(e.NewValue as Refresher).Refresh += handler;
if (e.OldValue != null)
(e.OldValue as Refresher).Refresh -= handler;
}
}
и, наконец, приложить его к ListBox в XAML:
<ListBox ItemsSource="{Binding Items}"
local:RefreshBehavior.Refresher="{Binding Refresher}"/>
Всё. Вызовите Refresher.DoRefresh()
в вашей модели просмотра, и это заставит обновление списка.
Это работает, но это действительно забивает квадратный штифт в круглое отверстие. Если бы я был вами, я бы сделал все возможное, чтобы попытаться сделать соответствующее уведомление об изменении коллекции в вашей модели. Я понимаю, что вы хотите оставить ObservableCollection вне своей модели, но есть способы автоматического уведомления об изменении прокси (например, Castle DynamicProxy).
Возможный дубликат [Как принудительно привязать WPF для обновления?] (Http://stackoverflow.com/questions/5676202/how-to-force-a-wpf-binding-to-refresh) – Steve
К сожалению, нет, это решение предназначено для обновления привязки с точки зрения, вызывая GetBindingExpression (dp) .UpdateTarget для элемента FrameworkElement. – FreddyFlares
Является ли ListBox не элементом FrameworkElement? – Steve