【问题标题】:Listbox with UserControl ItemTemplate always shows default values带有 UserControl ItemTemplate 的列表框始终显示默认值
【发布时间】:2014-02-04 21:20:37
【问题描述】:

首先,我有一个列表框,它试图接受 UserControl 作为 DataTemplate:

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

用户控件的内容看起来像:

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

然后我创建了几条消息,它们都包含不同的数据(列表框的 ItemSource 绑定到 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 );

在运行时,我询问了列表框的 Items 属性,所有数据看起来都正确,但是我在列表框中看到的只是具有默认数据值的 GeneralMcmMessage 用户控件的条目。关于为什么的任何想法?

另外,FWIW 我在用户控件类中使用 INotifyPropertyChanged:

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" );
        }
    }

【问题讨论】:

    标签: c# wpf user-controls listbox itemtemplate


    【解决方案1】:

    您是说显示GeneralMcmMessage 的DataTemplate 是实例化新的GeneralMcmMessage

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

    我建议不要创建用户控件的集合,而是创建模型对象的集合,并绑定到用户控件中的属性。

    无论哪种方式 - 您在代码中创建的对象将是您在 XAML 中创建的对象的 DataContext,因此删除 ElementName=_this 应该适当地绑定。在您的 UserControl 中尝试这个简化的 XAML。

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

    【讨论】:

    • 啊,所以当列表框在 Add() 期间初始化它时,删除“_this”可以让用户控件实例绑定到正确的数据上下文?这行得通,多么简单的疏忽。
    • 是的,我确实建议您将您的 UserControl 与您的模型对象分开。您正在为每条消息实例化 2 个用户控件。
    【解决方案2】:

    您没有发布 GeneralMcmMessage 的所有代码,因此我不知道您是否在用户控件中设置 DataContext,例如在 GeneralMcmMessage 的构造函数中。

    我尝试复制您的问题。

    用户控制GeneralMcmMessage背后的代码

       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;
            }
    
        }
    

    用户控制 GeneralMcmMessage XAML

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

    用户控制 GeneralMcmMessage 使用情况

    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);
            }
        }
    
    }
    

    用户控制 GeneralMcmMessage 使用 XAML

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

    如果这不能解决您的问题,请您发布所有 GeneralMcmMessage 吗?

    如果你愿意,我可以为你上传示例项目。

    谢谢

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-06-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多