Laden...

ListBox ItemTemplate - items werden nicht dargestellt

Erstellt von Coooder vor 9 Jahren Letzter Beitrag vor 9 Jahren 1.189 Views
C
Coooder Themenstarter:in
180 Beiträge seit 2011
vor 9 Jahren
ListBox ItemTemplate - items werden nicht dargestellt

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.

O
15 Beiträge seit 2015
vor 9 Jahren

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 😃

5.299 Beiträge seit 2008
vor 9 Jahren

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.

C
Coooder Themenstarter:in
180 Beiträge seit 2011
vor 9 Jahren

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 ...

5.299 Beiträge seit 2008
vor 9 Jahren

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.

C
Coooder Themenstarter:in
180 Beiträge seit 2011
vor 9 Jahren

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?

5.299 Beiträge seit 2008
vor 9 Jahren

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.

212 Beiträge seit 2008
vor 9 Jahren

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

I
256 Beiträge seit 2005
vor 9 Jahren

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

5.299 Beiträge seit 2008
vor 9 Jahren

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.

C
Coooder Themenstarter:in
180 Beiträge seit 2011
vor 9 Jahren

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!