Search code examples
c#wpflistboxcode-behindlistboxitem

My code-generated ListBox's items isn't showing any content


I have a code-generated window in WPF, (using dotnet core 3.0 preview 6), and when running my application gets the correct data, and the ListBox is populated with the correct number of rows, but none of them contains values

This is a test-project I'm doing to get familiar with code generated WPF as it's needed for an upcoming project we're doing at work; I would have preferred using XAML but my lead says that that will create issues with code-re-usability.

I at first made sure I used am object which is "clean", (my entities are setup for Linq2db, so I ensured that the attributes couldn't be the culprit), then I tested binding, (just got the "Error 40" -error code, but that isn't relevant to the main problem). I have also changed the type of boxes, but It does not help, (DataGrid did work but it's not what I'm looking for in a visual).

public class ChatWindow : IChatWindow
{
    private ObservableCollection<MessageDto> _observableMessages;
    private readonly IMessagesRepository _messagesRepository;

    public ChatWindow(IMessagesRepository messagesRepository)
    {
        _messagesRepository = messagesRepository;

        Task.Run(async () => { await Updater(); }).ConfigureAwait(false);
    }

    public async Task ShowAsync(User user)
    {
        var chatLog = new ListBox()
        {
            Name = "Chatview",
            ItemsSource = _observableMessages,
            ItemTemplate = new DataTemplate(typeof(MessageDto)),
            DataContext = _observableMessages
        };

        //var myBinding = new Binding("_observableMessages");
        //myBinding.Source = _observableMessages;
        //chatLog.SetBinding(ListBox.ItemsSourceProperty, myBinding);

        var input = new TextBox()
        {
            Name = "InputField",
            Background = new SolidColorBrush(Color.FromRgb(35, 35, 35))
        };

        var stackPanel = new StackPanel()
        {
            Children =
            {
                chatLog,
                input
            }
        };

        var window = new Window()
        {
            Name = "ChatWindow",
            Content = stackPanel,
        };

        window.Show();
    }

    private async Task Updater()
    {
        while (true)
        {
            var messages = await _messagesRepository.GetAllMessages(1);
            _observableMessages = new ObservableCollection<MessageDto>(messages.Select(m => new MessageDto()
            {
                Timestamp = m.Timestamp,
                From = m.From,
                Message = m.Message
            }));
            await Task.Delay(TimeSpan.FromSeconds(10));
        }
    }
}

class MessageDto
{
    public DateTime Timestamp { get; set; }
    public long From { get; set; }
    public string Message { get; set; }
}

Image of the resultant window, (some styling code was removed from the example code to reduce noise) enter image description here


Solution

  • Based on Flithor's comment, i did this and it worked perfectly:

    private DataTemplate GetDataTemplate()
        {
            var dataTemplate = new DataTemplate(typeof(MessageDto));
    
            FrameworkElementFactory stackPanelFactory = new FrameworkElementFactory(typeof(StackPanel));
            stackPanelFactory.SetValue(StackPanel.OrientationProperty, Orientation.Horizontal);
    
            FrameworkElementFactory timestamp = new FrameworkElementFactory(typeof(Label));
            timestamp.SetBinding(Label.ContentProperty, new Binding("Timestamp"));
            FrameworkElementFactory from = new FrameworkElementFactory(typeof(Label));
            from.SetBinding(Label.ContentProperty, new Binding("From"));
            FrameworkElementFactory message = new FrameworkElementFactory(typeof(Label));
            message.SetBinding(Label.ContentProperty, new Binding("Message"));
            stackPanelFactory.AppendChild(timestamp);
            stackPanelFactory.AppendChild(from);
            stackPanelFactory.AppendChild(message);
    
            dataTemplate.VisualTree = stackPanelFactory;
    
            return dataTemplate;
        }