Question

To start off, I have a listbox that is trying to accept a UserControl as the DataTemplate:

<ListBox VerticalAlignment="Stretch" Name="GeneralMcmView" Grid.Column="0"       HorizontalAlignment="Stretch" >
   <ListBox.ItemTemplate>
      <DataTemplate DataType="local:GeneralMcmMessage">
        <local:GeneralMcmMessage />
      </DataTemplate>
   </ListBox.ItemTemplate>
</ListBox>

With the contents of the usercontrol looking like:

<ContentControl FontFamily="Segoe UI" VerticalAlignment="Stretch" FontSize="10">
    <Grid VerticalAlignment="Stretch">
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>

        <StackPanel VerticalAlignment="Stretch" Orientation="Horizontal" Grid.Row="0">
            <TextBlock Name="MessageDateTime" Text="{Binding ElementName=_this, Path=TimeStamp, StringFormat=MM/dd/yyyy h:mm:ss.fff tt \'GMT\' (zzz)}" />
            <TextBlock Name="MessageTypeLabel" Margin="15,0,5,0" Text="Type:"/>
            <TextBlock Name="MessageType" Text="{Binding ElementName=_this, Path=Type}" />
        </StackPanel>
        <StackPanel VerticalAlignment="Stretch" Orientation="Horizontal" Grid.Row="1">
            <TextBlock Name="MessageNameLabel" Margin="0,0,5,0" Text="Message Name:" />
            <TextBlock Name="MessageNameValue" Text="{Binding ElementName=_this, Path=MessageName}" TextWrapping="Wrap" />
        </StackPanel>
        <StackPanel VerticalAlignment="Stretch" Orientation="Vertical" Grid.Row="2">
            <TextBlock Name="MessageLabel" Text="Message:"/>
            <TextBlock Name="Message" Margin="10,0,0,0" Text="{Binding ElementName=_this, Path=MessageContent}" />
        </StackPanel>
    </Grid>
</ContentControl>

I then create a couple messages, all with different data (The Listbox's ItemSource is bound to the GeneralMessages ObservableCollection):

GeneralMcmMessage newMsg = new GeneralMcmMessage()
        {
            MessageId = e.McmMessageViewInfo.Id,
            TimeStamp = e.McmMessageViewInfo.MessageDateTime,
            Type = e.McmMessageViewInfo.MessageType.ToString(),
            MessageName = e.McmMessageViewInfo.MessageName,
            MessageContent = e.McmMessageViewInfo.Message.ToString()
        };

        GeneralMessages.Add( newMsg );

During runtime I interrogate the Items property of the listbox and all the data looks correct, however all I see in the listbox are entries of the GeneralMcmMessage User Control with default data values. Any ideas as to why?

Also, FWIW I am using INotifyPropertyChanged in the usercontrol class:

public partial class GeneralMcmMessage : UserControl, INotifyPropertyChanged
{
    private Constants.PiuModule piuModule = Constants.PiuModule.MCM;
    private string className = "GeneralMcmMessage";

    /// <summary>
    /// Event for notifying listeners that a property changed.  Part of   INotifyPropertyChanged
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;

    public int MessageId { get; set; }

    private DateTime timeStamp;
    public DateTime TimeStamp
    {
        get
        {
            return timeStamp;
        }
        set
        {
            timeStamp = value;

            OnNotifyPropertyChanged( "TimeStamp" );
        }
    }
Was it helpful?

Solution

You're saying that the DataTemplate to display a GeneralMcmMessage is to instantiate new GeneralMcmMessage.

  <DataTemplate DataType="local:GeneralMcmMessage">
    <local:GeneralMcmMessage />
  </DataTemplate>

I'd recommend instead of making a collection of your UserControl to make a collection of your model object instead, and bind to the properties within that within your UserControl.

Either way though - the object you created in code will be the DataContext for the one you created in XAML so removing the ElementName=_this should bind appropriately. Try this simplified XAML in your UserControl instead.

<StackPanel VerticalAlignment="Stretch" Orientation="Horizontal" Grid.Row="0">
  <TextBlock Name="MessageDateTime" Text="{Binding TimeStamp, StringFormat=MM/dd/yyyy h:mm:ss.fff tt \'GMT\' (zzz)}" />
  <TextBlock Name="MessageTypeLabel" Margin="15,0,5,0" Text="Type:"/>
  <TextBlock Name="MessageType" Text="{Binding Type}" />
</StackPanel>
<StackPanel VerticalAlignment="Stretch" Orientation="Horizontal" Grid.Row="1">
  <TextBlock Name="MessageNameLabel" Margin="0,0,5,0" Text="Message Name:" />
  <TextBlock Name="MessageNameValue" Text="{Binding MessageName}" TextWrapping="Wrap" />
</StackPanel>
<StackPanel VerticalAlignment="Stretch" Orientation="Vertical" Grid.Row="2">
  <TextBlock Name="MessageLabel" Text="Message:"/>
  <TextBlock Name="Message" Margin="10,0,0,0" Text="{Binding MessageContent}" />
</StackPanel>

OTHER TIPS

You don’t post all code of GeneralMcmMessage hence I don’t know if you set DataContext in user control for example in constructor of GeneralMcmMessage.

I tried replicate your problem.

User control GeneralMcmMessage code behind

   public partial class GeneralMcmMessage : UserControl, INotifyPropertyChanged
    {
        private int _messageId;

        public int MessageId
        {
            get
            {
                return _messageId;
            }

            set
            {
                _messageId = value;
                OnPropertyChanged("MessageId");
            }
        }

        private DateTime _timeStamp;

        public DateTime TimeStamp
        {
            get
            {
                return _timeStamp;
            }

            set
            {
                _timeStamp = value;

                OnPropertyChanged("TimeStamp");
            }
        }

        public GeneralMcmMessage()
        {
            InitializeComponent();

           //don’t set data context here
           //DataContext = this;
        }

    }

User control GeneralMcmMessage XAML

<StackPanel>
    <TextBlock Margin="5" FontSize="20"  Text="{Binding Path=MessageId}"/>
    <TextBlock Margin="5" FontSize="20"  Text="{Binding Path=TimeStamp}"/>
</StackPanel>

User control GeneralMcmMessage usage

public partial class MainWindow : Window, INotifyPropertyChanged
{
    private ObservableCollection<GeneralMcmMessage> _generalMessages;

    public MainWindow()
    {
        InitializeComponent();

        DataContext = this;
    }

    public ObservableCollection<GeneralMcmMessage> GeneralMcmMessages
    {
        get { return _generalMessages; }

        set
        {
            _generalMessages = value;
            OnPropertyChanged("GeneralMcmMessages");
        }
    }


    private void MainWindow_OnLoaded(object sender, RoutedEventArgs e)
    {
        GeneralMcmMessages = new ObservableCollection<GeneralMcmMessage>();

        for (int i = 0; i < 10; i++)
        {
            var newMsg = new GeneralMcmMessage
            {
                MessageId = i,
                TimeStamp = DateTime.Now,
            };

            GeneralMcmMessages.Add(newMsg);
        }
    }

}

User control GeneralMcmMessage usage XAML

<ListBox x:Name="ListBox"
         Margin="5"
         ItemsSource="{Binding Path=GeneralMcmMessages}">
    <ListBox.ItemTemplate>
        <DataTemplate DataType="stackoverflow:GeneralMcmMessage">
            <stackoverflow:GeneralMcmMessage/>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

If this not solve your problem could you please post all GeneralMcmMessage?

If you want I can upload sample project for you.

Thank you

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top