好几个问题
第一
这是我的实施,但它没有工作,我怎么能让它运作?
<Grid> // xaml part
<Button Content="Start Crawling Root Sites - This Deletes All Data" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="279" Command="{Binding StartCrawling}" Click="click_start_Crawling" />
<ListBox Name="lstBoxEvents" HorizontalAlignment="Left" Height="138" Margin="294,10,0,0" VerticalAlignment="Top" Width="312">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="1" Text="{Binding ocEvents}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
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);
}
}
运行多线程时的第二个问题,如果多个线程访问AddMsgToEvents函数并添加变量,列表框是否会自动刷新而没有任何问题?
非常感谢
答案 0 :(得分:1)
这一行:
public static ObservableCollection<string> ocEvents = new ObservableCollection<string>();
这既不是依赖属性也不是实现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));
}
绑定到静态类/属性有一些奇怪之处,你必须以不同的方式绑定。我现在要睡觉了,所以我无法提供和示例。在上面的例子中,我将创建一个vm,以及一个用于获取我的事件而不是使我的vm为unittestable的服务(创建提供事件的服务的接口,并在vm上具有event属性)。
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,或者你需要对你的绑定进行一些修改,以获得支持或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);
}
}
将此接口提供给vm的ctor(TDD :))或codebehind ctor。将其分配并存储在IOC cotainer,servicelocator或其他任何内容中。
希望它有所帮助,
干杯,
了Stian