Hallo,
Ich habe eine ListBox und dessen ItemSource habe ich auf eine ObservableCollection gebindet.
Dann habe ich noch ein ItemTemplate hinzugefügt. Wenn in die Collection jetzt ein item hinzugefügt wird, wird jedoch nichts angezeigt ... Was ich merkwürdig finde, da ich das in einer anderen ListBox genau so gemacht habe und es da funktionierte ... aber hier mal der code
<ListBox Grid.Row="0" Margin="10" ItemsSource="{Binding ChatContent, Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<Border Background="{Binding Color}" Padding="10">
<TextBlock TextWrapping="Wrap" Text="{Binding Message}" />
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
private ObservableCollection<ChatMessage> _chatContent = new ObservableCollection<ChatMessage>();
public ObservableCollection<ChatMessage> ChatContent
{
get { return _chatContent; }
set
{
if (value != _chatContent) {
_chatContent = value;
NotifyPropertyChanged();
}
}
}
.
.
.
public async void Connect()
{
Connection = new HubConnection(ServerURI);
KeyValuePair<string, string> userId = new KeyValuePair<string, string>("userId", ClientRuntimeContext.CurrentAppUser.Id.ToString());
Connection.Headers.Add(userId);
HubProxy = Connection.CreateHubProxy("MyHub");
HubProxy.On<MessageInfo>("AddMessage", (messageInfo) =>
{
// hier wirds hinzugefügt nachdem die SignalR nachricht angekommen ist
ChatMessage cm = new ChatMessage(messageInfo);
ChatContent.Add(cm);
});
public class ChatMessage
{
public string UserFrom { get; set; }
public string UserTo { get; set; }
public Brush Color { get; set; }
public string Message { get; set; }
public ChatMessage(MessageInfo messageInfo)
{
if (messageInfo.UserFrom.Id == ClientRuntimeContext.CurrentAppUser.Id)
Color = Brushes.AliceBlue;
else
Color = Brushes.Crimson;
Message = messageInfo.Message;
}
}
Würd mich freuen wenn mir jemand helfen kann.
Musst du deinem NotifyPropertyChanged(); nicht noch etwas übergeben?
Ich bin es so gewohnt:
NotifyPropertyChanged("ChatContent");
Allerdings kann ich auch gerade auf der völlig falschen Spur sein 😃
probier das mal ohne async.
aber wenn ich mich recht erinnere, gabs dabei sogar einen Fehler, wenn man einer gebundenen OC nebenläufig ein Item addete.
Der frühe Apfel fängt den Wurm.
Musst du deinem NotifyPropertyChanged(); nicht noch etwas übergeben?
Ich bin es so gewohnt:
NotifyPropertyChanged("ChatContent");
public void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
Durch das Attribute gehts auch ohne 😃
probier das mal ohne async.
hab ich gemacht, geht leider immer noch nich 😕 aber dafür wurde jetzt mal nen Fehler geworfen> Fehlermeldung:
....keine Änderungen der "SourceCollection" unterstützt, wenn diese nicht von einem Dispatcher-Thread aus erfolgen.
hab es jetzt so
Dispatcher.CurrentDispatcher.Invoke(() => { ChatContent.Add(cm); });
und so
Dispatcher.CurrentDispatcher.BeginInvoke((Action) (() =>
{
ChatContent.Add(cm);
}));
probiert ... leider bringt er dann auch die gleiche meldung ...
immerhin - da scheint HasePfeffer.
Deine Oberfläche scheint in einem anderen Thread zu laufen als dein Viewmodel. und da gibts diese Fehlermeldung.
Ich finds zwar ausserordentlich, dasss der Fehler kommt, grad wenn du ohne Nebenläufigkeit agierst, aber das wird iwas ihn deiner Anwendung sein, in das wir hier keinen Einblick haben.
Als Dispatcher musst du den Dispatcher des Threads der Oberfläche nehmen.
Bei mir geht das zB, wenn ich im CodeBehind der App.Xaml im Konstruktor mir Dispatcher.CurrentDispatcher merke und public static zugreifbar mache.
Der frühe Apfel fängt den Wurm.
Als Dispatcher musst du den Dispatcher des Threads der Oberfläche nehmen.
Bei mir geht das zB, wenn ich im CodeBehind der App.Xaml im Konstruktor mir Dispatcher.CurrentDispatcher merke und public static zugreifbar mache.
Aber ich greif doch auf den Dispatcher.CurrentDispatcher zu. Ob ich den in der App.xaml.cs nochmal extra ablege und darauf zugreife sollte doch kein unterschied machen oder?
klar macht das einen Unterschied.
CurrentDispatcher gibt dir den Dispatcher des Current Thread - (deswegen heißt das auch CurrentDispatcher)
Rufst du das also von einem nebenläufigen Thread aus, kriegst du den falschen Dispatcher.
Der frühe Apfel fängt den Wurm.
Geht es vielleicht so?
HubProxy = Connection.CreateHubProxy("MyHub");
HubProxy.On<MessageInfo>("AddMessage", (messageInfo) =>
{
Dispatcher.CurrentDispatcher.BeginInvoke((Action) (() =>
{
ChatMessage cm = new ChatMessage(messageInfo);
ChatContent.Add(cm);
}));
});
Ich hatte heute das selbe Problem und habe es so gelöst, danach ist die Exception nicht mehr gekommen.
Gruß
Christoph
Das hat überhaut nix mit dem Dispatcher zu tun.
Bindet einfach nach dem .Add den Source neu Chat.Item
Das notitfychanged wird beim .Add nicht aufgerufen, sondern nur bei der Zuweisung.
also die russische Methode
ChatMessage cm = new ChatMessage(messageInfo);
ChatContent.Add(cm);
ListBox.ItemSource = ChatContent;
lg
Das würde dem MVVM-Pattern widersprechen.
Nach MVVM reicht es, eine Listbox nur einmal an die ItemsSource zu binden, und man macht das im Xaml.
Der frühe Apfel fängt den Wurm.
Ok das mit dem Dispatcher in die App.xaml.cs zu packen hat Funktioniert!
Jetzt nach deiner Erklärung machts auch sinn =D
Vielen dank an dich und die anderen!